Merge "Added header to frequently contacted in people for tablet."
diff --git a/res/drawable-hdpi/ic_ab_dialer_holo_dark.png b/res/drawable-hdpi/ic_ab_dialer_holo_dark.png
new file mode 100644
index 0000000..ecfeb2d
--- /dev/null
+++ b/res/drawable-hdpi/ic_ab_dialer_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_minus_holo_dark.png b/res/drawable-hdpi/ic_minus_holo_dark.png
new file mode 100644
index 0000000..f228047
--- /dev/null
+++ b/res/drawable-hdpi/ic_minus_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_play_holo_dark.png b/res/drawable-hdpi/ic_play_holo_dark.png
index c8cd127..d5fd235 100644
--- a/res/drawable-hdpi/ic_play_holo_dark.png
+++ b/res/drawable-hdpi/ic_play_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_plus_holo_dark.png b/res/drawable-hdpi/ic_plus_holo_dark.png
new file mode 100644
index 0000000..d7b2804
--- /dev/null
+++ b/res/drawable-hdpi/ic_plus_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_ab_dialer_holo_dark.png b/res/drawable-mdpi/ic_ab_dialer_holo_dark.png
new file mode 100644
index 0000000..51ad9e3
--- /dev/null
+++ b/res/drawable-mdpi/ic_ab_dialer_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_minus_holo_dark.png b/res/drawable-mdpi/ic_minus_holo_dark.png
new file mode 100644
index 0000000..a020991
--- /dev/null
+++ b/res/drawable-mdpi/ic_minus_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_play_holo_dark.png b/res/drawable-mdpi/ic_play_holo_dark.png
index ecce105..a31671d 100644
--- a/res/drawable-mdpi/ic_play_holo_dark.png
+++ b/res/drawable-mdpi/ic_play_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_plus_holo_dark.png b/res/drawable-mdpi/ic_plus_holo_dark.png
new file mode 100644
index 0000000..4f6397c
--- /dev/null
+++ b/res/drawable-mdpi/ic_plus_holo_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_ab_dialer_holo_dark.png b/res/drawable-xhdpi/ic_ab_dialer_holo_dark.png
new file mode 100644
index 0000000..3f43a82
--- /dev/null
+++ b/res/drawable-xhdpi/ic_ab_dialer_holo_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_minus_holo_dark.png b/res/drawable-xhdpi/ic_minus_holo_dark.png
new file mode 100644
index 0000000..0e95a6b
--- /dev/null
+++ b/res/drawable-xhdpi/ic_minus_holo_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_play_holo_dark.png b/res/drawable-xhdpi/ic_play_holo_dark.png
index c97ca43..afa6bb0 100644
--- a/res/drawable-xhdpi/ic_play_holo_dark.png
+++ b/res/drawable-xhdpi/ic_play_holo_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_plus_holo_dark.png b/res/drawable-xhdpi/ic_plus_holo_dark.png
new file mode 100644
index 0000000..b869bf9
--- /dev/null
+++ b/res/drawable-xhdpi/ic_plus_holo_dark.png
Binary files differ
diff --git a/res/layout-sw580dp-w1000dp/contact_detail_fragment.xml b/res/layout-sw580dp-w1000dp/contact_detail_fragment.xml
new file mode 100644
index 0000000..9dd3690
--- /dev/null
+++ b/res/layout-sw580dp-w1000dp/contact_detail_fragment.xml
@@ -0,0 +1,65 @@
+<?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.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts"
+    android:id="@+id/contact_detail"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/panel_content">
+
+    <!-- Placeholder for empty list -->
+    <include
+        android:id="@android:id/empty"
+        layout="@layout/contact_detail_empty"
+        android:visibility="gone" />
+
+    <!-- Real list -->
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <ImageView android:id="@+id/photo"
+            android:scaleType="centerCrop"
+            android:layout_width="@dimen/detail_contact_photo_size"
+            android:layout_height="@dimen/detail_contact_photo_size"
+            android:layout_marginLeft="@dimen/detail_contact_photo_margin"
+            android:layout_marginRight="@dimen/detail_contact_photo_margin"
+            android:layout_marginTop="@dimen/detail_contact_photo_margin"
+            android:layout_marginBottom="@dimen/detail_contact_photo_margin"/>
+
+        <ListView android:id="@android:id/list"
+            android:layout_width="0dip"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:divider="@null"/>
+
+   </LinearLayout>
+
+    <!-- "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="right"
+        android:layout_marginRight="40dip"
+        android:layout_marginTop="10dip"
+        android:layout_marginBottom="10dip" />
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout-sw580dp-w1000dp/contact_detail_header_view.xml b/res/layout-sw580dp-w1000dp/contact_detail_header_view.xml
deleted file mode 100644
index 82432a0..0000000
--- a/res/layout-sw580dp-w1000dp/contact_detail_header_view.xml
+++ /dev/null
@@ -1,149 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/banner"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:paddingBottom="28dip">
-
-    <TextView
-        android:id="@+id/attribution"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/detail_header_attribution_height"
-        android:paddingRight="16dip"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textColor="?android:attr/textColorTertiary"
-        android:gravity="right|center_vertical"
-        android:singleLine="true" />
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal">
-
-        <ImageView
-            android:id="@+id/photo"
-            android:layout_marginLeft="-1dip"
-            android:layout_width="96dip"
-            android:layout_height="96dip" />
-
-        <LinearLayout
-            android:layout_width="0px"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:layout_gravity="top"
-            android:orientation="vertical">
-
-            <View
-                android:layout_width="match_parent"
-                android:layout_height="1px"
-                android:background="@color/contact_detail_header_divider_color" />
-
-            <LinearLayout
-                android:layout_width="fill_parent"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:paddingTop="16dip"
-                android:layout_marginLeft="@dimen/detail_header_view_margin">
-
-                <!-- Star -->
-                <CheckBox
-                    android:id="@+id/star"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_marginTop="4dip"
-                    android:layout_gravity="top"
-                    android:contentDescription="@string/description_star"
-                    android:visibility="invisible"
-                    style="?android:attr/starStyle" />
-
-                <!-- Name, PhoneticName, Directory -->
-                <LinearLayout
-                    android:layout_width="fill_parent"
-                    android:layout_height="wrap_content"
-                    android:paddingLeft="@dimen/detail_header_view_margin"
-                    android:orientation="vertical">
-
-                    <TextView
-                        android:id="@+id/name"
-                        style="@style/ContactDetailHeaderTextView"
-                        android:textSize="@dimen/contact_name_text_size" />
-
-                    <TextView
-                        android:id="@+id/phonetic_name"
-                        style="@style/ContactDetailHeaderTextView"
-                        android:textAppearance="?android:attr/textAppearanceMedium"
-                        android:layout_marginTop="-2dip"
-                        android:visibility="gone" />
-
-                    <TextView
-                        android:id="@+id/organization"
-                        style="@style/ContactDetailHeaderTextView"
-                        android:layout_marginTop="-2dip"
-                        android:visibility="gone"
-                        android:textAppearance="?android:attr/textAppearanceMedium"
-                        android:textColor="?android:attr/textColorTertiary" />
-                </LinearLayout>
-            </LinearLayout>
-
-            <LinearLayout
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal">
-
-                <!-- Status info -->
-                <LinearLayout
-                    android:id="@+id/status_container"
-                    android:layout_width="0px"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="1"
-                    android:orientation="vertical"
-                    android:background="@drawable/statusbox_landscape_holo_light"
-                    android:layout_marginLeft="10dip"
-                    android:layout_marginTop="30dip"
-                    android:paddingLeft="52dip"
-                    android:paddingTop="12dip"
-                    android:paddingRight="16dip"
-                    android:paddingBottom="12dip"
-                    android:visibility="gone">
-
-                    <TextView
-                        android:id="@+id/status"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:textAppearance="?android:attr/textAppearanceSmall"
-                        android:textColor="?android:attr/textColorSecondary"
-                        android:maxLines="3"
-                        android:ellipsize="end"
-                        android:visibility="gone" />
-
-                    <TextView
-                        android:id="@+id/status_date"
-                        android:layout_width="match_parent"
-                        android:layout_height="0dip"
-                        android:layout_weight="1"
-                        android:textAppearance="?android:attr/textAppearanceSmall"
-                        android:textColor="?android:attr/textColorTertiary"
-                        android:gravity="right"
-                        android:visibility="gone" />
-                </LinearLayout>
-            </LinearLayout>
-        </LinearLayout>
-    </LinearLayout>
-</LinearLayout>
diff --git a/res/layout-sw580dp-w1000dp/detail_header_contact_with_updates.xml b/res/layout-sw580dp-w1000dp/detail_header_contact_with_updates.xml
new file mode 100644
index 0000000..1a1a3bb
--- /dev/null
+++ b/res/layout-sw580dp-w1000dp/detail_header_contact_with_updates.xml
@@ -0,0 +1,68 @@
+<?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.
+-->
+
+<!--
+  This is a header entry in the contact details list for when the contact has social updates. The
+  entry shows the contact's basic info and maintains vertical padding to ensure that the first
+  contact detail is visible (and below the tab carousel). The photo is not displayed here
+  because it will be shown in the tab carousel.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:padding="20dip">
+
+    <ImageView
+        android:id="@+id/photo"
+        android:scaleType="centerCrop"
+        android:layout_width="@dimen/detail_contact_photo_size"
+        android:layout_height="@dimen/detail_contact_photo_size" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:paddingLeft="10dip"
+        android:paddingRight="10dip">
+
+        <TextView
+            android:id="@+id/name"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:textSize="@dimen/detail_header_name_text_size" />
+
+        <TextView
+            android:id="@+id/company"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+
+        <CheckBox
+            android:id="@+id/star"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical"
+            android:contentDescription="@string/description_star"
+            style="?android:attr/starStyle" />
+
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout-sw580dp-w1000dp/detail_header_contact_without_updates.xml b/res/layout-sw580dp-w1000dp/detail_header_contact_without_updates.xml
new file mode 100644
index 0000000..415bbbf
--- /dev/null
+++ b/res/layout-sw580dp-w1000dp/detail_header_contact_without_updates.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+
+<!--
+  This is a header entry in the contact details list for when the contact does not have social
+  updates, which means that the contact's basic info will scroll with the list of details. The
+  photo is not included because it will be displayed in a static place elsewhere.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:paddingTop="20dip">
+
+    <TextView
+        android:id="@+id/name"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceLarge"
+        android:textSize="@dimen/detail_header_name_text_size" />
+
+    <TextView
+        android:id="@+id/company"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+
+    <CheckBox
+        android:id="@+id/star"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="top"
+        android:contentDescription="@string/description_star"
+        style="?android:attr/starStyle" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout-sw580dp/contact_detail_header_view.xml b/res/layout-sw580dp/contact_detail_header_view.xml
deleted file mode 100644
index 95a5617..0000000
--- a/res/layout-sw580dp/contact_detail_header_view.xml
+++ /dev/null
@@ -1,142 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/banner"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:paddingBottom="28dip">
-
-    <TextView
-        android:id="@+id/attribution"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/detail_header_attribution_height"
-        android:paddingRight="24dip"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textColor="?android:attr/textColorTertiary"
-        android:gravity="right|center_vertical"
-        android:singleLine="true" />
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal">
-
-        <ImageView
-            android:id="@+id/photo"
-            android:layout_marginLeft="@dimen/detail_header_view_margin"
-            android:layout_width="96dip"
-            android:layout_height="96dip" />
-
-        <LinearLayout
-            android:layout_width="0px"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:orientation="vertical"
-            android:layout_gravity="top">
-
-            <View
-                android:layout_width="match_parent"
-                android:layout_height="1px"
-                android:background="@color/contact_detail_header_divider_color" />
-
-            <LinearLayout
-                android:layout_width="fill_parent"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:paddingTop="16dip"
-                android:layout_marginLeft="@dimen/detail_header_view_margin">>
-
-                <!-- Star -->
-                <CheckBox
-                    android:id="@+id/star"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_marginTop="4dip"
-                    android:layout_gravity="top"
-                    android:contentDescription="@string/description_star"
-                    android:visibility="invisible"
-                    style="?android:attr/starStyle" />
-
-                <!-- Name, PhoneticName, Directory -->
-                <LinearLayout
-                    android:layout_width="fill_parent"
-                    android:layout_height="wrap_content"
-                    android:paddingLeft="@dimen/detail_header_view_margin"
-                    android:orientation="vertical">
-
-                    <TextView
-                        android:id="@+id/name"
-                        style="@style/ContactDetailHeaderTextView"
-                        android:textSize="@dimen/contact_name_text_size" />
-
-                    <TextView
-                        android:id="@+id/phonetic_name"
-                        style="@style/ContactDetailHeaderTextView"
-                        android:textAppearance="?android:attr/textAppearanceMedium"
-                        android:layout_marginTop="-2dip"
-                        android:visibility="gone" />
-
-                    <TextView
-                        android:id="@+id/organization"
-                        style="@style/ContactDetailHeaderTextView"
-                        android:layout_marginTop="-2dip"
-                        android:visibility="gone"
-                        android:textAppearance="?android:attr/textAppearanceMedium"
-                        android:textColor="?android:attr/textColorTertiary" />
-                </LinearLayout>
-            </LinearLayout>
-        </LinearLayout>
-    </LinearLayout>
-
-    <!-- Status info -->
-    <LinearLayout
-        android:id="@+id/status_container"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:background="@drawable/statusbox_portrait_holo_light"
-        android:layout_marginLeft="16dip"
-        android:layout_marginRight="24dip"
-        android:layout_marginTop="10dip"
-        android:paddingLeft="12dip"
-        android:paddingTop="36dip"
-        android:paddingRight="16dip"
-        android:paddingBottom="12dip"
-        android:visibility="gone">
-
-        <TextView
-            android:id="@+id/status"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorSecondary"
-            android:maxLines="3"
-            android:ellipsize="end"
-            android:visibility="gone" />
-
-        <TextView
-            android:id="@+id/status_date"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorTertiary"
-            android:gravity="right"
-            android:visibility="gone" />
-    </LinearLayout>
-</LinearLayout>
diff --git a/res/layout-sw580dp/detail_header_contact_with_updates.xml b/res/layout-sw580dp/detail_header_contact_with_updates.xml
new file mode 100644
index 0000000..e909434
--- /dev/null
+++ b/res/layout-sw580dp/detail_header_contact_with_updates.xml
@@ -0,0 +1,52 @@
+<?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.
+-->
+
+<!--
+  This is a header entry in the contact details list for when the contact has social updates. The
+  entry shows the contact's basic info and maintains vertical padding to ensure that the first
+  contact detail is visible (and below the tab carousel). The photo is not displayed here
+  because it will be shown in the tab carousel.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:paddingTop="@dimen/detail_tab_carousel_height"
+    android:layout_marginTop="20dip">
+
+    <TextView
+        android:id="@+id/name"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceLarge"
+        android:textSize="@dimen/detail_header_name_text_size" />
+
+    <TextView
+        android:id="@+id/company"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+
+    <CheckBox
+        android:id="@+id/star"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="top"
+        android:contentDescription="@string/description_star"
+        style="?android:attr/starStyle" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout-sw580dp/detail_header_contact_without_updates.xml b/res/layout-sw580dp/detail_header_contact_without_updates.xml
new file mode 100644
index 0000000..4ae31c8
--- /dev/null
+++ b/res/layout-sw580dp/detail_header_contact_without_updates.xml
@@ -0,0 +1,55 @@
+<?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.
+-->
+
+<!--
+  This is a header entry in the contact details list for when the contact does not have social
+  updates, which means that the contact's photo and basic info will scroll with the list of details.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:paddingTop="20dip">
+
+    <ImageView
+        android:id="@+id/photo"
+        android:scaleType="centerCrop"
+        android:layout_width="@dimen/detail_contact_photo_size"
+        android:layout_height="@dimen/detail_contact_photo_size" />
+
+    <TextView
+        android:id="@+id/name"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceLarge"
+        android:textSize="@dimen/detail_header_name_text_size" />
+
+    <TextView
+        android:id="@+id/company"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+
+    <CheckBox
+        android:id="@+id/star"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="top"
+        android:contentDescription="@string/description_star"
+        style="?android:attr/starStyle" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/simple_contact_detail_header_view_list_item.xml b/res/layout-w470dp/detail_header_contact_with_updates.xml
similarity index 74%
copy from res/layout/simple_contact_detail_header_view_list_item.xml
copy to res/layout-w470dp/detail_header_contact_with_updates.xml
index eea4ac4..588957e 100644
--- a/res/layout/simple_contact_detail_header_view_list_item.xml
+++ b/res/layout-w470dp/detail_header_contact_with_updates.xml
@@ -14,15 +14,11 @@
      limitations under the License.
 -->
 
+<!--
+  This is a header entry in the contact details list for when the contact has social updates.
+  This is empty because all the information will be displayed elsewhere.
+-->
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content">
-
-    <ImageView
-        android:id="@+id/photo"
-        android:scaleType="centerCrop"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/detail_tab_carousel_height" />
-
-</FrameLayout>
\ No newline at end of file
+    android:layout_height="0dip"/>
\ No newline at end of file
diff --git a/res/layout/simple_contact_detail_header_view_list_item.xml b/res/layout-w470dp/detail_header_contact_without_updates.xml
similarity index 74%
copy from res/layout/simple_contact_detail_header_view_list_item.xml
copy to res/layout-w470dp/detail_header_contact_without_updates.xml
index eea4ac4..44ea04c 100644
--- a/res/layout/simple_contact_detail_header_view_list_item.xml
+++ b/res/layout-w470dp/detail_header_contact_without_updates.xml
@@ -14,15 +14,11 @@
      limitations under the License.
 -->
 
+<!--
+  This is a header entry in the contact details list for when the contact does not have social
+  updates. This is empty because all the information will be displayed elsewhere.
+-->
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content">
-
-    <ImageView
-        android:id="@+id/photo"
-        android:scaleType="centerCrop"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/detail_tab_carousel_height" />
-
-</FrameLayout>
\ No newline at end of file
+    android:layout_height="0dip"/>
\ No newline at end of file
diff --git a/res/layout/call_detail.xml b/res/layout/call_detail.xml
index c20df49..02dd098 100644
--- a/res/layout/call_detail.xml
+++ b/res/layout/call_detail.xml
@@ -20,29 +20,12 @@
     android:orientation="horizontal"
     android:gravity="top"
 >
-    <LinearLayout
-        android:id="@+id/action_bar"
-        android:layout_width="match_parent"
-        android:layout_height="?attr/call_detail_action_bar_height"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentTop="true"
-        android:orientation="horizontal"
-        android:background="@drawable/call_log_action_bar_bg"
-    >
-        <ImageView
-            android:id="@+id/action_bar_home"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:src="@drawable/ic_call_log_home"
-        />
-    </LinearLayout>
-
     <FrameLayout
         android:id="@+id/voicemail_status"
-        android:layout_below="@id/action_bar"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_alignParentLeft="true"
+        android:layout_alignParentTop="true"
         android:visibility="gone"
     >
         <include layout="@layout/call_log_voicemail_status"/>
@@ -51,7 +34,7 @@
     <ImageView
         android:id="@+id/contact_background"
         android:layout_width="match_parent"
-        android:layout_height="?attr/call_detail_contact_background_height"
+        android:layout_height="@dimen/call_detail_contact_background_height"
         android:layout_alignParentLeft="true"
         android:layout_below="@id/voicemail_status"
         android:adjustViewBounds="true"
@@ -73,7 +56,7 @@
     </LinearLayout>
     <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="?attr/call_detail_contact_background_overlay_height"
+        android:layout_height="@dimen/call_detail_contact_background_overlay_height"
         android:background="#3F000000"
         android:layout_alignParentLeft="true"
         android:layout_alignBottom="@id/contact_background"
@@ -81,19 +64,21 @@
     <RelativeLayout
         android:id="@+id/contact_text"
         android:layout_width="match_parent"
-        android:layout_height="?attr/call_detail_contact_background_overlay_height"
+        android:layout_height="@dimen/call_detail_contact_background_overlay_height"
         android:layout_alignParentLeft="true"
         android:layout_alignBottom="@id/contact_background"
-        android:paddingLeft="5dip"
+        android:paddingLeft="@dimen/call_detail_contact_name_margin"
     >
         <ImageView
             android:id="@+id/main_action"
-            android:layout_width="?attr/call_detail_action_icon_size"
+            android:layout_width="@dimen/call_log_call_action_size"
             android:layout_height="match_parent"
             android:gravity="center_vertical"
             android:scaleType="center"
             android:layout_alignParentRight="true"
             android:layout_alignParentBottom="true"
+            android:layout_marginRight="@dimen/call_log_outer_margin"
+            android:layout_marginLeft="@dimen/call_log_inner_margin"
         />
         <RelativeLayout
             android:layout_width="wrap_content"
diff --git a/res/layout/call_detail_history_item.xml b/res/layout/call_detail_history_item.xml
index 3b28cfc..069ade9 100644
--- a/res/layout/call_detail_history_item.xml
+++ b/res/layout/call_detail_history_item.xml
@@ -20,15 +20,15 @@
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:background="?attr/call_log_secondary_background_color"
-    android:padding="5dip"
+    android:padding="@dimen/call_log_indent_margin"
 >
-    <ImageView
+    <FrameLayout
         android:id="@+id/call_type_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
         android:layout_alignParentLeft="true"
-        android:layout_marginRight="5dip"
+        android:layout_marginRight="@dimen/call_log_icon_margin"
     />
     <TextView
         android:id="@+id/call_type_text"
diff --git a/res/layout/call_log_action_call.xml b/res/layout/call_log_action_call.xml
index 0f15a23..062af6a 100644
--- a/res/layout/call_log_action_call.xml
+++ b/res/layout/call_log_action_call.xml
@@ -19,35 +19,48 @@
     <LinearLayout
         android:id="@+id/divider"
         android:layout_width="wrap_content"
-        android:layout_height="?attr/call_log_list_contact_photo_size"
+        android:layout_height="wrap_content"
         android:layout_alignParentRight="true"
+        android:layout_centerInParent="true"
         android:orientation="horizontal"
     >
         <ImageView
-            android:id="@+id/play_icon"
+            android:id="@+id/unheard_icon"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="?attr/call_log_inner_margin"
+            android:layout_marginLeft="@dimen/call_log_inner_margin"
             android:layout_gravity="center_vertical"
             android:scaleType="center"
             android:src="@drawable/ic_unheard_voicemail_holo_dark"
             android:visibility="gone"
+            android:contentDescription="@string/description_call_log_unheard_voicemail"
         />
         <View
             android:layout_width="1px"
-            android:layout_height="?attr/call_log_list_call_action_size"
+            android:layout_height="@dimen/call_log_call_action_size"
             android:layout_gravity="center_vertical"
-            android:layout_marginLeft="?attr/call_log_inner_margin"
+            android:layout_marginLeft="@dimen/call_log_inner_margin"
             android:background="@drawable/ic_divider_dashed_holo_dark"
         />
         <ImageView
             android:id="@+id/call_icon"
-            android:layout_width="?attr/call_log_list_call_action_size"
-            android:layout_height="?attr/call_log_list_call_action_size"
-            android:layout_marginLeft="?attr/call_log_inner_margin"
+            android:layout_width="@dimen/call_log_call_action_size"
+            android:layout_height="@dimen/call_log_call_action_size"
+            android:layout_marginLeft="@dimen/call_log_inner_margin"
             android:layout_gravity="center_vertical"
             android:scaleType="center"
-            android:src="@drawable/ic_dial_action_call"
+            android:src="@drawable/ic_ab_dialer_holo_dark"
+            android:contentDescription="@string/description_call_log_call_button"
+        />
+        <ImageView
+            android:id="@+id/play_icon"
+            android:layout_width="@dimen/call_log_call_action_size"
+            android:layout_height="@dimen/call_log_call_action_size"
+            android:layout_marginLeft="@dimen/call_log_inner_margin"
+            android:layout_gravity="center_vertical"
+            android:scaleType="center"
+            android:src="@drawable/ic_play_holo_dark"
+            android:contentDescription="@string/description_call_log_play_button"
         />
     </LinearLayout>
 
diff --git a/res/layout/call_log_contact_photo.xml b/res/layout/call_log_contact_photo.xml
index a9add82..6afb1ab 100644
--- a/res/layout/call_log_contact_photo.xml
+++ b/res/layout/call_log_contact_photo.xml
@@ -1,10 +1,21 @@
 <?xml version="1.0" encoding="utf-8"?>
 <merge xmlns:android="http://schemas.android.com/apk/res/android">
-    <QuickContactBadge
+    <FrameLayout
         android:id="@+id/contact_photo"
-        android:layout_width="?attr/call_log_list_contact_photo_size"
-        android:layout_height="?attr/call_log_list_contact_photo_size"
+        android:layout_width="@dimen/call_log_list_contact_photo_size"
+        android:layout_height="@dimen/call_log_list_contact_photo_size"
         android:layout_alignParentLeft="true"
-        android:layout_gravity="center_vertical"
-    />
+        android:layout_centerInParent="true"
+    >
+        <QuickContactBadge
+            android:id="@+id/quick_contact_photo"
+            android:layout_width="@dimen/call_log_list_contact_photo_size"
+            android:layout_height="@dimen/call_log_list_contact_photo_size"
+        />
+        <ImageView
+            android:id="@+id/plain_contact_photo"
+            android:layout_width="@dimen/call_log_list_contact_photo_size"
+            android:layout_height="@dimen/call_log_list_contact_photo_size"
+        />
+    </FrameLayout>
 </merge>
diff --git a/res/layout/call_log_incoming_call_icon.xml b/res/layout/call_log_incoming_call_icon.xml
new file mode 100644
index 0000000..7bb7054
--- /dev/null
+++ b/res/layout/call_log_incoming_call_icon.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/call_log_incoming_call_icon"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_marginRight="@dimen/call_log_icon_margin"
+    android:src="@drawable/ic_call_incoming_holo_dark"
+    android:contentDescription="@string/description_call_log_incoming_call"
+/>
diff --git a/res/layout/call_log_list_item.xml b/res/layout/call_log_list_item.xml
index 890026e..fcccf07 100644
--- a/res/layout/call_log_list_item.xml
+++ b/res/layout/call_log_list_item.xml
@@ -27,10 +27,10 @@
     <FrameLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="?attr/call_log_outer_margin"
-        android:layout_marginRight="?attr/call_log_outer_margin"
-        android:layout_marginTop="?attr/call_log_inner_margin"
-        android:layout_marginBottom="?attr/call_log_inner_margin"
+        android:layout_marginLeft="@dimen/call_log_outer_margin"
+        android:layout_marginRight="@dimen/call_log_outer_margin"
+        android:layout_marginTop="@dimen/call_log_inner_margin"
+        android:layout_marginBottom="@dimen/call_log_inner_margin"
     >
         <!--
             This layout may represent either a call log item or one of the
@@ -63,7 +63,7 @@
                 android:id="@+id/call_log_header_text"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="?attr/call_log_inner_margin"
+                android:layout_marginLeft="@dimen/call_log_inner_margin"
                 android:textSize="14sp"
                 android:textStyle="bold"
                 android:textColor="?attr/call_log_header_color"
diff --git a/res/layout/call_log_list_item_layout.xml b/res/layout/call_log_list_item_layout.xml
index 4fbe426..e754bf7 100644
--- a/res/layout/call_log_list_item_layout.xml
+++ b/res/layout/call_log_list_item_layout.xml
@@ -17,11 +17,12 @@
 <merge xmlns:android="http://schemas.android.com/apk/res/android">
     <RelativeLayout
         android:layout_width="wrap_content"
-        android:layout_height="?attr/call_log_list_contact_photo_size"
+        android:layout_height="wrap_content"
         android:layout_toRightOf="@id/contact_photo"
         android:layout_toLeftOf="@id/divider"
+        android:layout_centerInParent="true"
         android:layout_alignWithParentIfMissing="true"
-        android:layout_marginLeft="?attr/call_log_inner_margin"
+        android:layout_marginLeft="@dimen/call_log_inner_margin"
     >
         <include layout="@layout/call_log_phone_call_details"/>
     </RelativeLayout>
diff --git a/res/layout/call_log_missed_call_icon.xml b/res/layout/call_log_missed_call_icon.xml
new file mode 100644
index 0000000..4a37229
--- /dev/null
+++ b/res/layout/call_log_missed_call_icon.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/call_log_missed_call_icon"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_marginRight="@dimen/call_log_icon_margin"
+    android:src="@drawable/ic_call_missed_holo_dark"
+    android:contentDescription="@string/description_call_log_missed_call"
+/>
diff --git a/res/layout/call_log_outgoing_call_icon.xml b/res/layout/call_log_outgoing_call_icon.xml
new file mode 100644
index 0000000..67841be
--- /dev/null
+++ b/res/layout/call_log_outgoing_call_icon.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/call_log_outgoing_call_icon"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_marginRight="@dimen/call_log_icon_margin"
+    android:src="@drawable/ic_call_outgoing_holo_dark"
+    android:contentDescription="@string/description_call_log_outgoing_call"
+/>
diff --git a/res/layout/call_log_phone_call_details.xml b/res/layout/call_log_phone_call_details.xml
index cf26fb6..5a4131e 100644
--- a/res/layout/call_log_phone_call_details.xml
+++ b/res/layout/call_log_phone_call_details.xml
@@ -16,68 +16,73 @@
 
 <merge xmlns:android="http://schemas.android.com/apk/res/android">
     <LinearLayout
-        android:id="@+id/call_type"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentLeft="true"
-        android:layout_alignParentBottom="true"
+        android:layout_centerInParent="true"
         android:gravity="center_vertical"
+        android:orientation="vertical"
     >
+        <TextView
+            android:id="@+id/name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="?attr/call_log_primary_text_color"
+            android:textSize="18sp"
+            android:singleLine="true"
+        />
+        <TextView
+            android:id="@+id/number"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="?attr/call_log_secondary_text_color"
+            android:textSize="14sp"
+            android:singleLine="true"
+        />
         <LinearLayout
-            android:id="@+id/call_type_icons"
+            android:id="@+id/call_type"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginRight="?attr/call_log_inner_margin"
-        />
-        <TextView
-            android:id="@+id/call_type_name"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textColor="?attr/call_log_secondary_text_color"
-            android:textSize="14sp"
-            android:layout_marginRight="?attr/call_log_inner_margin"
-            android:singleLine="true"
-        />
-        <TextView
-            android:id="@+id/call_type_separator"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginRight="?attr/call_log_inner_margin"
-            android:textColor="?attr/call_log_secondary_text_color"
-            android:textSize="14sp"
-            android:text="@string/call_log_type_date_separator"
-            android:singleLine="true"
-        />
-        <TextView
-            android:id="@+id/date"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textColor="?attr/call_log_secondary_text_color"
-            android:textSize="14sp"
-            android:layout_toRightOf="@id/call_type"
-            android:layout_alignParentBottom="true"
-            android:singleLine="true"
-        />
+            android:orientation="horizontal"
+        >
+            <LinearLayout
+                android:id="@+id/call_type_icons"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginRight="@dimen/call_log_icon_margin"
+                android:layout_gravity="center_vertical"
+                android:orientation="horizontal"
+            />
+            <TextView
+                android:id="@+id/call_type_name"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginRight="@dimen/call_log_inner_margin"
+                android:layout_gravity="center_vertical"
+                android:textColor="?attr/call_log_secondary_text_color"
+                android:textSize="14sp"
+                android:singleLine="true"
+            />
+            <TextView
+                android:id="@+id/call_type_separator"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginRight="@dimen/call_log_inner_margin"
+                android:layout_gravity="center_vertical"
+                android:textColor="?attr/call_log_secondary_text_color"
+                android:textSize="14sp"
+                android:text="@string/call_log_type_date_separator"
+                android:singleLine="true"
+            />
+            <TextView
+                android:id="@+id/date"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical"
+                android:textColor="?attr/call_log_secondary_text_color"
+                android:textSize="14sp"
+                android:singleLine="true"
+            />
+        </LinearLayout>
     </LinearLayout>
-    <TextView
-        android:id="@+id/number"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textColor="?attr/call_log_secondary_text_color"
-        android:textSize="14sp"
-        android:layout_alignParentLeft="true"
-        android:layout_above="@id/call_type"
-        android:singleLine="true"
-    />
-    <TextView
-        android:id="@+id/name"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textColor="?attr/call_log_primary_text_color"
-        android:textSize="18sp"
-        android:layout_alignParentLeft="true"
-        android:layout_above="@id/number"
-        android:paddingBottom="2dp"
-        android:singleLine="true"
-    />
 </merge>
diff --git a/res/layout/call_log_voicemail_icon.xml b/res/layout/call_log_voicemail_icon.xml
new file mode 100644
index 0000000..cfd6a2d
--- /dev/null
+++ b/res/layout/call_log_voicemail_icon.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/call_log_voicemail_icon"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_marginRight="@dimen/call_log_icon_margin"
+    android:src="@drawable/ic_call_voicemail_holo_dark"
+    android:contentDescription="@string/description_call_log_voicemail"
+/>
diff --git a/res/layout/contact_detail_header_view.xml b/res/layout/contact_detail_header_view.xml
deleted file mode 100644
index 328a5ff..0000000
--- a/res/layout/contact_detail_header_view.xml
+++ /dev/null
@@ -1,126 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/banner"
-    android:layout_width="match_parent"
-    android:layout_height="150dip">
-
-    <ImageView android:id="@+id/photo"
-        android:scaleType="centerCrop"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentLeft="true"
-        />
-
-    <!-- Transparent view to overlay on the contact's photo
-    (to allow white text to appear over a white photo). -->
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentLeft="true"
-        android:background="#000000"
-        android:alpha=".25"
-        />
-
-    <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:layout_alignParentLeft="true"
-        android:layout_marginLeft="10dip"
-        android:orientation="vertical" >
-
-        <TextView android:id="@+id/name"
-            android:layout_width="wrap_content"
-            android:layout_height="0dip"
-            android:layout_weight="1"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:gravity="bottom"
-            android:textSize="@dimen/detail_header_name_text_size"
-            android:textColor="@color/detail_header_view_text_color"
-         />
-
-        <TextView android:id="@+id/phonetic_name"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textColor="@color/detail_header_view_text_color"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:layout_marginTop="-2dip"
-            android:visibility="gone"
-        />
-
-        <TextView android:id="@+id/organization"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textColor="@color/detail_header_view_text_color"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:layout_marginTop="-2dip"
-            android:visibility="gone"
-        />
-
-        <TextView android:id="@+id/attribution"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorSecondary"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:layout_marginTop="-2dip"
-            android:visibility="gone"
-        />
-
-        <TextView android:id="@+id/status"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="@color/detail_header_view_text_color"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:layout_marginTop="-2dip"
-            android:visibility="gone"
-        />
-
-        <TextView android:id="@+id/status_date"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textSize="12sp"
-            android:layout_marginTop="-2dip"
-            android:visibility="gone"
-        />
-    </LinearLayout>
-
-    <CheckBox
-        android:id="@+id/star"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="10dip"
-        android:layout_marginRight="10dip"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentRight="true"
-        android:layout_gravity="center_vertical"
-        android:contentDescription="@string/description_star"
-        android:visibility="invisible"
-        style="?android:attr/starStyle"
-    />
-</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/simple_contact_detail_header_view_list_item.xml b/res/layout/detail_header_contact_with_updates.xml
similarity index 69%
copy from res/layout/simple_contact_detail_header_view_list_item.xml
copy to res/layout/detail_header_contact_with_updates.xml
index eea4ac4..00d1b76 100644
--- a/res/layout/simple_contact_detail_header_view_list_item.xml
+++ b/res/layout/detail_header_contact_with_updates.xml
@@ -14,15 +14,12 @@
      limitations under the License.
 -->
 
+<!--
+  This is a header entry in the contact details list for when the contact has social updates. The
+  entry maintains vertical padding to ensure that the first contact detail is visible (and below
+  the tab carousel). No information has to be displayed in this header.
+-->
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content">
-
-    <ImageView
-        android:id="@+id/photo"
-        android:scaleType="centerCrop"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/detail_tab_carousel_height" />
-
-</FrameLayout>
\ No newline at end of file
+    android:layout_height="@dimen/detail_tab_carousel_height"/>
\ No newline at end of file
diff --git a/res/layout/simple_contact_detail_header_view_list_item.xml b/res/layout/detail_header_contact_without_updates.xml
similarity index 84%
rename from res/layout/simple_contact_detail_header_view_list_item.xml
rename to res/layout/detail_header_contact_without_updates.xml
index eea4ac4..a5d4687 100644
--- a/res/layout/simple_contact_detail_header_view_list_item.xml
+++ b/res/layout/detail_header_contact_without_updates.xml
@@ -14,6 +14,10 @@
      limitations under the License.
 -->
 
+<!--
+  This is a header entry in the contact details list for when the contact does not have social
+  updates, which means that the contact's photo will scroll with the list of details.
+-->
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
diff --git a/res/layout/external_raw_contact_editor_view.xml b/res/layout/external_raw_contact_editor_view.xml
index be0c8ba..eb36cb2 100644
--- a/res/layout/external_raw_contact_editor_view.xml
+++ b/res/layout/external_raw_contact_editor_view.xml
@@ -20,121 +20,116 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="horizontal"
->
+    android:paddingBottom="10dip">
 
     <!-- Left side color bar -->
     <ImageView
         android:id="@+id/color_bar"
         android:layout_width="4dip"
         android:layout_height="match_parent"
-        android:visibility="gone"
-    />
+        android:visibility="gone"/>
 
     <!-- The content -->
     <LinearLayout
         android:layout_width="0dip"
         android:layout_height="wrap_content"
         android:layout_weight="1"
-        android:orientation="vertical"
-    >
+        android:orientation="vertical">
 
         <!-- Account info header -->
-        <RelativeLayout android:id="@+id/header"
-            android:layout_height="64dip"
+        <ImageView android:id="@+id/header_color_bar"
             android:layout_width="match_parent"
-        >
-
-            <ImageView android:id="@+id/header_color_bar"
-                android:layout_width="match_parent"
-                android:layout_height="4dip"
-                android:layout_marginBottom="5dip"
-                android:background="@color/edit_divider"
-            />
-
-            <ImageView android:id="@+id/account_icon"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginLeft="7dip"
-                android:layout_marginRight="7dip"
-                android:layout_centerVertical="true"
-                android:layout_below="@id/header_color_bar"
-            />
-
-            <TextView android:id="@+id/account_type"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_toRightOf="@+id/account_icon"
-                android:layout_alignTop="@id/account_icon"
-                android:layout_marginTop="-4dip"
-
-                android:textSize="24sp"
-                android:textColor="?android:attr/textColorPrimary"
-                android:singleLine="true"
-            />
-
-            <TextView android:id="@+id/account_name"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_toRightOf="@+id/account_icon"
-                android:layout_alignBottom="@+id/account_icon"
-                android:layout_marginBottom="2dip"
-                android:textAppearance="?android:attr/textAppearanceSmall"
-                android:textColor="?android:attr/textColorPrimary"
-                android:singleLine="true"
-            />
-
-            <View
-                android:layout_width="match_parent"
-                android:layout_height="1px"
-                android:layout_alignParentBottom="true"
-
-                android:background="?android:attr/listDivider"
-            />
-
-        </RelativeLayout>
-
-        <FrameLayout
-            android:id="@+id/stub_photo"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingLeft="12dip"
-            android:paddingTop="10dip">
-
-            <include
-                android:id="@+id/edit_photo"
-                layout="@layout/item_photo_editor" />
-
-        </FrameLayout>
-
-        <TextView android:id="@+id/read_only_name"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="6dip"
-            android:layout_marginBottom="6dip"
-            android:layout_marginLeft="10dip"
-
-            android:textAppearance="?android:attr/textAppearanceLarge"
-        />
-
-        <View
-            android:layout_width="match_parent"
-            android:layout_height="1px"
-            android:background="?android:attr/listDivider"
-        />
+            android:layout_height="4dip"
+            android:layout_marginBottom="5dip"
+            android:background="@color/edit_divider"/>
 
         <TextView
             android:id="@+id/read_only_warning"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginTop="13dip"
-            android:layout_marginBottom="13dip"
-            android:layout_marginLeft="13dip"
-
+            android:paddingTop="10dip"
+            android:paddingLeft="10dip"
+            android:paddingRight="10dip"
             android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorPrimary"
-            android:drawableLeft="?android:attr/alertDialogIcon"
-            android:drawablePadding="10dip"
-        />
+            android:textColor="?android:attr/textColorTertiary"/>
+
+        <LinearLayout
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:orientation="horizontal"
+            android:paddingLeft="10dip"
+            android:paddingRight="10dip">
+
+            <LinearLayout
+                android:id="@+id/account"
+                android:layout_height="wrap_content"
+                android:layout_width="0dip"
+                android:layout_weight="1"
+                android:orientation="vertical"
+                android:background="?android:attr/selectableItemBackground">
+
+                <TextView
+                    android:id="@+id/account_type"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="?android:attr/textAppearanceMedium"
+                    android:singleLine="true" />
+
+                <TextView
+                     android:id="@+id/account_name"
+                     android:layout_width="wrap_content"
+                     android:layout_height="wrap_content"
+                     android:textAppearance="?android:attr/textAppearanceSmall"
+                     android:textColor="?android:attr/textColorTertiary"
+                     android:singleLine="true" />
+
+            </LinearLayout>
+
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent">
+
+                <ImageView
+                     android:id="@+id/account_icon"
+                     android:layout_width="45dip"
+                     android:layout_height="45dip"
+                     android:layout_gravity="center_vertical" />
+
+            </FrameLayout>
+
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:orientation="horizontal"
+            android:paddingTop="20dip"
+            android:paddingLeft="10dip"
+            android:paddingRight="10dip">
+
+            <TextView android:id="@+id/read_only_name"
+                android:layout_width="0dip"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:gravity="center_vertical"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:textColor="?android:attr/textColorTertiary"
+                android:textStyle="bold"/>
+
+            <FrameLayout
+                android:id="@+id/stub_photo"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content">
+
+                <include
+                    android:id="@+id/edit_photo"
+                    layout="@layout/item_photo_editor" />
+
+            </FrameLayout>
+
+        </LinearLayout>
 
         <Button
             android:id="@+id/button_edit_externally"
@@ -143,20 +138,13 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="13dip"
             android:layout_marginBottom="13dip"
-            android:layout_marginLeft="13dip"
-        />
-
-        <View
-            android:layout_width="match_parent"
-            android:layout_height="1px"
-            android:background="?android:attr/listDivider"
-        />
+            android:layout_marginLeft="13dip"/>
 
         <LinearLayout android:id="@+id/sect_general"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:orientation="vertical"
-        />
+            android:orientation="vertical"/>
+
     </LinearLayout>
 
 </com.android.contacts.editor.ExternalRawContactEditorView>
diff --git a/res/layout/group_list_header_item.xml b/res/layout/group_browse_list_account_header.xml
similarity index 98%
rename from res/layout/group_list_header_item.xml
rename to res/layout/group_browse_list_account_header.xml
index b38920f..73684c1 100644
--- a/res/layout/group_list_header_item.xml
+++ b/res/layout/group_browse_list_account_header.xml
@@ -33,6 +33,7 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textColor="@color/people_app_theme_color"
             android:textStyle="bold"
+            android:textAllCaps="true"
             android:singleLine="true"/>
 
         <TextView
diff --git a/res/layout/group_browse_list_item.xml b/res/layout/group_browse_list_item.xml
index b829704..ecdc132 100644
--- a/res/layout/group_browse_list_item.xml
+++ b/res/layout/group_browse_list_item.xml
@@ -14,21 +14,48 @@
      limitations under the License.
 -->
 
-<view
+<LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    class="com.android.contacts.group.GroupBrowseListAdapter$GroupListItem"
-    android:orientation="horizontal"
+    android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:paddingBottom="10dip"
     style="@style/GroupBrowseListItem">
 
+    <ImageView
+        android:id="@+id/divider"
+        android:layout_width="match_parent"
+        android:layout_height="1dip"
+        android:layout_marginBottom="10dip"
+        android:paddingLeft="10dip"
+        android:paddingRight="10dip"
+        android:scaleType="fitXY"
+        android:src="@color/people_app_theme_color"/>
+
+    <include
+        android:id="@+id/group_list_header"
+        layout="@layout/group_browse_list_account_header"
+        android:visibility="gone" />
+
     <TextView
         android:id="@+id/label"
         android:layout_height="wrap_content"
         android:layout_width="wrap_content"
-        android:padding="10dip"
-        android:textAppearance="?android:attr/textAppearanceLarge"
+        android:paddingLeft="10dip"
+        android:paddingRight="10dip"
+        android:textAppearance="?android:attr/textAppearanceMedium"
         android:ellipsize="end"
         android:singleLine="true" />
 
-</view>
+    <TextView
+        android:id="@+id/count"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:paddingLeft="10dip"
+        android:paddingRight="10dip"
+        android:textAppearance="?android:attr/textAppearanceSmall"
+        android:textColor="?android:attr/textColorTertiary"
+        android:ellipsize="end"
+        android:singleLine="true" />
+
+</LinearLayout>
diff --git a/res/layout/playback_layout.xml b/res/layout/playback_layout.xml
index bebb0a0..1fb36be 100644
--- a/res/layout/playback_layout.xml
+++ b/res/layout/playback_layout.xml
@@ -61,8 +61,8 @@
             android:thumb="@drawable/seek_bar_thumb"
             android:thumbOffset="0dip"
             android:background="@drawable/dialpad_background"
-            android:paddingLeft="35dip"
-            android:paddingRight="35dip"
+            android:paddingLeft="50dip"
+            android:paddingRight="50dip"
             android:paddingTop="10dip"
             android:paddingBottom="20dip"
             android:layout_margin="4dip"
@@ -81,7 +81,7 @@
         />
         <ImageButton
             android:id="@+id/rate_decrease_button"
-            android:src="@drawable/ic_menu_remove_field_holo_light"
+            android:src="@drawable/ic_minus_holo_dark"
             android:layout_width="30dip"
             android:layout_height="wrap_content"
             android:background="@android:color/transparent"
@@ -92,7 +92,7 @@
         />
         <ImageButton
             android:id="@+id/rate_increase_button"
-            android:src="@drawable/ic_menu_add_field_holo_light"
+            android:src="@drawable/ic_plus_holo_dark"
             android:layout_width="30dip"
             android:layout_height="wrap_content"
             android:background="@android:color/transparent"
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index e155cbc..18b86be 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -144,7 +144,7 @@
     <dimen name="detail_network_icon_size">32dip</dimen>
 
     <!-- Font size for the display name in header of the contact detail page -->
-    <dimen name="detail_header_name_text_size">30sp</dimen>
+    <dimen name="detail_header_name_text_size">36sp</dimen>
 
     <!-- Padding to be used between a visible scrollbar and the contact list -->
     <dimen name="list_visible_scrollbar_padding">40dip</dimen>
@@ -214,4 +214,16 @@
 
     <!--  ContactTile Layouts -->
     <dimen name="contact_tile_shadowbox_height">48dip</dimen>
+
+    <!-- Call Log -->
+    <dimen name="call_log_call_action_size">32dip</dimen>
+    <dimen name="call_log_icon_margin">4dip</dimen>
+    <dimen name="call_log_inner_margin">8dip</dimen>
+    <dimen name="call_log_outer_margin">16dip</dimen>
+    <dimen name="call_log_indent_margin">24dip</dimen>
+    <dimen name="call_log_list_contact_photo_size">64dip</dimen>
+    <dimen name="call_detail_contact_background_height">174dip</dimen>
+    <dimen name="call_detail_contact_background_overlay_height">42dip</dimen>
+    <dimen name="call_detail_contact_name_margin">24dip</dimen>
+    <dimen name="call_detail_action_bar_height">60dip</dimen>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 75e3249..4069c49 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1293,8 +1293,8 @@
     <!-- Checkbox asking the user if they want to display a particular photo for a contact -->
     <string name="use_photo_as_primary">Use this photo</string>
 
-    <!-- Text used to explain that a contact cannot be edited since the data is read only -->
-    <string name="contact_read_only"><xliff:g id="source" example="Gmail">%1$s</xliff:g> contact information is not editable on this device.</string>
+    <!-- Text used to explain that a contact cannot be edited since the data is read only [CHAR LIMIT=40] -->
+    <string name="contact_read_only">Not editable on this device</string>
 
     <!-- Text describing that a contact has no information available other than name and photo -->
     <string name="no_contact_details">No additional information for this contact</string>
@@ -1557,6 +1557,12 @@
         <item quantity="other"><xliff:g id="count">%1$d</xliff:g> people from <xliff:g id="account_type">%2$s</xliff:g></item>
     </plurals>
 
+    <!-- Subtitle of a group (in the group list) that describes how many people are in the current group [CHAR LIMIT=30] -->
+    <plurals name="group_list_num_contacts_in_group">
+        <item quantity="one"><xliff:g id="count">%1$d</xliff:g> person</item>
+        <item quantity="other"><xliff:g id="count">%1$d</xliff:g> people</item>
+    </plurals>
+
     <!-- Toast displayed when the user creates a new contact and attempts to join it
       with another before entering any data  [CHAR LIMIT=256] -->
     <string name="toast_join_with_empty_contact">Please enter contact name before joining
@@ -1639,6 +1645,17 @@
    server directly to listen to the voicemails. [CHAR LIMIT=20] -->
     <string name="voicemail_status_action_call_server">Call voicemail</string>
 
+    <!-- The slowest voicemail playback speed. [CHAR LIMIT=30] -->
+    <string name="voicemail_speed_slowest">slowest speed</string>
+    <!-- Slower than normal voicemail playback speed. [CHAR LIMIT=30] -->
+    <string name="voicemail_speed_slower">slow speed</string>
+    <!--  Normal voicemail playback speed. [CHAR LIMIT=30] -->
+    <string name="voicemail_speed_normal">normal speed</string>
+    <!--  Faster than normal pvoicemail playback speed. [CHAR LIMIT=30] -->
+    <string name="voicemail_speed_faster">fast speed</string>
+    <!--  Fastest voicemail playback speed. [CHAR LIMIT=30] -->
+    <string name="voicemail_speed_fastest">fastest speed</string>
+
     <!-- The counter for calls in a group in the call log [CHAR LIMIT=5] -->
     <string name="call_log_item_count">(%1$d)</string>
 
@@ -1660,4 +1677,56 @@
     <!--  Used to display as default status when the contact is busy or Do not disturb for chat [CHAR LIMIT=19] -->
     <string name="status_busy">Busy</string>
 
+    <!-- String describing the icon in the call log used to place a call.
+
+        Note: AccessibilityServices use this attribute to announce what the view represents.
+              This is especially valuable for views without textual representation like ImageView.
+    -->
+    <string name="description_call_log_call_button">Call number</string>
+
+    <!-- String describing the icon in the call log used to play a voicemail.
+
+        Note: AccessibilityServices use this attribute to announce what the view represents.
+              This is especially valuable for views without textual representation like ImageView.
+    -->
+    <string name="description_call_log_play_button">Play voicemail</string>
+
+    <!-- String describing the icon in the call log used to represent an incoming call.
+
+        Note: AccessibilityServices use this attribute to announce what the view represents.
+              This is especially valuable for views without textual representation like ImageView.
+    -->
+    <string name="description_call_log_incoming_call">Incoming call</string>
+
+    <!-- String describing the icon in the call log used to represent an outgoing call.
+
+        Note: AccessibilityServices use this attribute to announce what the view represents.
+              This is especially valuable for views without textual representation like ImageView.
+    -->
+
+    <string name="description_call_log_outgoing_call">Outgoing call</string>
+
+    <!-- String describing the icon in the call log used to represent a missed call.
+
+        Note: AccessibilityServices use this attribute to announce what the view represents.
+              This is especially valuable for views without textual representation like ImageView.
+    -->
+
+    <string name="description_call_log_missed_call">Missed call</string>
+
+    <!-- String describing the icon in the call log used to represent a voicemail left to the user.
+
+        Note: AccessibilityServices use this attribute to announce what the view represents.
+              This is especially valuable for views without textual representation like ImageView.
+    -->
+    <string name="description_call_log_voicemail">Voicemail</string>
+
+    <!-- String describing the icon in the call log used to represent an unheard voicemail left to
+         the user.
+
+        Note: AccessibilityServices use this attribute to announce what the view represents.
+              This is especially valuable for views without textual representation like ImageView.
+    -->
+    <string name="description_call_log_unheard_voicemail">Unheard voicemail</string>
+
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index d16590e..d26affc 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -41,12 +41,7 @@
         <item name="list_item_header_underline_height">1px</item>
         <item name="list_item_header_underline_color">@color/people_app_theme_color</item>
         <item name="contact_filter_popup_width">320dip</item>
-        <!-- CallLogList -->
-        <item name="call_log_list_contact_photo_size">64dip</item>
-        <item name="call_log_list_call_action_size">32dip</item>
         <!-- CallLog -->
-        <item name="call_log_inner_margin">8dip</item>
-        <item name="call_log_outer_margin">16dip</item>
         <item name="call_log_primary_text_color">#FFFFFF</item>
         <item name="call_log_primary_background_color">#000000</item>
         <item name="call_log_secondary_text_color">#888888</item>
@@ -58,18 +53,11 @@
         <item name="call_log_voicemail_status_text_color">#000000</item>
     </style>
 
-    <style name="CallDetailActivityTheme" parent="android:Theme.Holo">
-        <item name="android:windowNoTitle">true</item>
+    <style name="CallDetailActivityTheme" parent="android:Theme.Holo.SplitActionBarWhenNarrow">
         <item name="android:gravity">top</item>
         <item name="call_detail_transparent_background">#CC000000</item>
-        <item name="call_detail_contact_background_height">150dip</item>
-        <item name="call_detail_contact_background_overlay_height">70dip</item>
-        <item name="call_detail_action_bar_height">60dip</item>
-        <item name="call_detail_action_icon_size">60dip</item>
         <item name="call_detail_contact_background_overlay_alpha">0.25</item>
         <!-- CallLog -->
-        <item name="call_log_inner_margin">8dip</item>
-        <item name="call_log_outer_margin">16dip</item>
         <item name="call_log_primary_text_color">#FFFFFF</item>
         <item name="call_log_primary_background_color">#000000</item>
         <item name="call_log_secondary_text_color">#FFFFFF</item>
@@ -154,17 +142,10 @@
 
     <declare-styleable name="CallDetailActivity">
         <attr name="call_detail_transparent_background" format="color" />
-        <attr name="call_detail_contact_background_height" format="dimension" />
-        <attr name="call_detail_contact_background_overlay_height" format="dimension" />
         <attr name="call_detail_contact_background_overlay_alpha" format="float" />
-        <attr name="call_detail_contact_photo_size" format="dimension" />
-        <attr name="call_detail_action_icon_size" format="dimension" />
-        <attr name="call_detail_action_bar_height" format="dimension" />
     </declare-styleable>
 
     <declare-styleable name="CallLog">
-        <attr name="call_log_inner_margin" format="dimension" />
-        <attr name="call_log_outer_margin" format="dimension" />
         <attr name="call_log_primary_text_color" format="color" />
         <attr name="call_log_primary_background_color" format="color" />
         <attr name="call_log_secondary_text_color" format="color" />
@@ -172,11 +153,6 @@
         <attr name="call_log_header_color" format="color" />
     </declare-styleable>
 
-    <declare-styleable name="CallLogList">
-        <attr name="call_log_list_contact_photo_size" format="dimension" />
-        <attr name="call_log_list_call_action_size" format="dimension" />
-    </declare-styleable>
-
     <declare-styleable name="VoicemailStatus">
         <attr name="call_log_voicemail_status_height" format="dimension" />
         <attr name="call_log_voicemail_status_background_color" format="color" />
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index 68c9f61..813ebb1 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -24,6 +24,7 @@
 import com.android.contacts.voicemail.VoicemailStatusHelper.StatusMessage;
 import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
 
+import android.app.ActionBar;
 import android.app.FragmentManager;
 import android.app.ListActivity;
 import android.content.ContentResolver;
@@ -81,7 +82,6 @@
     private CallTypeHelper mCallTypeHelper;
     private PhoneNumberHelper mPhoneNumberHelper;
     private PhoneCallDetailsHelper mPhoneCallDetailsHelper;
-    private View mHomeActionView;
     private ImageView mMainActionView;
     private ImageView mContactBackgroundView;
 
@@ -147,33 +147,21 @@
         mResources = getResources();
 
         mPhoneCallDetailsViews = PhoneCallDetailsViews.fromView(getWindow().getDecorView());
-        mCallTypeHelper = new CallTypeHelper(getResources(),
-                getResources().getDrawable(R.drawable.ic_call_incoming_holo_dark),
-                getResources().getDrawable(R.drawable.ic_call_outgoing_holo_dark),
-                getResources().getDrawable(R.drawable.ic_call_missed_holo_dark),
-                getResources().getDrawable(R.drawable.ic_call_voicemail_holo_dark));
+        mCallTypeHelper = new CallTypeHelper(getResources(), mInflater);
         mPhoneNumberHelper = new PhoneNumberHelper(mResources, getVoicemailNumber());
-        mPhoneCallDetailsHelper = new PhoneCallDetailsHelper(this, mResources, mCallTypeHelper,
+        mPhoneCallDetailsHelper = new PhoneCallDetailsHelper(mResources, mCallTypeHelper,
                 mPhoneNumberHelper);
         mVoicemailStatusHelper = new VoicemailStatusHelperImpl();
         mAsyncQueryHandler = new CallDetailActivityQueryHandler(this);
         mStatusMessageView = findViewById(R.id.voicemail_status);
         mStatusMessageText = (TextView) findViewById(R.id.voicemail_status_message);
         mStatusMessageAction = (TextView) findViewById(R.id.voicemail_status_action);
-        mHomeActionView = findViewById(R.id.action_bar_home);
         mMainActionView = (ImageView) findViewById(R.id.main_action);
         mContactBackgroundView = (ImageView) findViewById(R.id.contact_background);
         mDefaultCountryIso = ContactsUtils.getCurrentCountryIso(this);
         mContactPhotoManager = ContactPhotoManager.getInstance(this);
         getListView().setOnItemClickListener(this);
-        mHomeActionView.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                // We want this to start the call log if this activity was not started from the
-                // call log itself.
-                CallDetailActivity.this.finish();
-            }
-        });
+        configureActionBar();
     }
 
     @Override
@@ -286,7 +274,7 @@
 
         // Set the details header, based on the first phone call.
         mPhoneCallDetailsHelper.setPhoneCallDetails(mPhoneCallDetailsViews,
-                details[0], false, false);
+                details[0], false, false, true);
 
         // Cache the details about the phone number.
         final Uri numberCallUri = mPhoneNumberHelper.getCallUri(mNumber);
@@ -658,8 +646,32 @@
                         new Intent(Intent.ACTION_DIAL, mPhoneNumberHelper.getCallUri(mNumber)));
                 return true;
 
+            case android.R.id.home: {
+                onHomeSelected();
+                return true;
+            }
+
             default:
                 throw new IllegalArgumentException();
         }
     }
+
+    private void configureActionBar() {
+        ActionBar actionBar = getActionBar();
+        if (actionBar != null) {
+            actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME,
+                    ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE
+                    | ActionBar.DISPLAY_SHOW_HOME);
+            actionBar.setIcon(R.drawable.ic_ab_dialer_holo_dark);
+        }
+    }
+
+    /** Invoked when the user presses the home button in the action bar. */
+    private void onHomeSelected() {
+        Intent intent = new Intent(Intent.ACTION_VIEW, Calls.CONTENT_URI);
+        // This will open the call log even if the detail view has been opened directly.
+        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        startActivity(intent);
+        finish();
+    }
 }
diff --git a/src/com/android/contacts/ContactLoader.java b/src/com/android/contacts/ContactLoader.java
index fa0ffb2..4078598 100644
--- a/src/com/android/contacts/ContactLoader.java
+++ b/src/com/android/contacts/ContactLoader.java
@@ -16,9 +16,12 @@
 
 package com.android.contacts;
 
+import com.android.contacts.model.AccountType;
+import com.android.contacts.model.AccountTypeManager;
 import com.android.contacts.util.DataStatus;
 import com.android.contacts.util.StreamItemEntry;
 import com.android.contacts.util.StreamItemPhotoEntry;
+import com.google.android.collect.Lists;
 import com.google.common.annotations.VisibleForTesting;
 
 import android.content.ContentResolver;
@@ -44,23 +47,20 @@
 import android.provider.ContactsContract.DisplayNameSources;
 import android.provider.ContactsContract.Groups;
 import android.provider.ContactsContract.RawContacts;
-import android.provider.ContactsContract.StreamItems;
 import android.provider.ContactsContract.StreamItemPhotos;
+import android.provider.ContactsContract.StreamItems;
 import android.text.TextUtils;
 import android.util.Log;
 
 import java.io.ByteArrayOutputStream;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 /**
  * Loads a single Contact and all it constituent RawContacts.
@@ -71,6 +71,7 @@
     private Uri mLookupUri;
     private boolean mLoadGroupMetaData;
     private boolean mLoadStreamItems;
+    private final boolean mLoadInvitableAccountTypes;
     private Result mContact;
     private ForceLoadContentObserver mObserver;
     private boolean mDestroyed;
@@ -113,6 +114,7 @@
         private final ArrayList<Entity> mEntities;
         private ArrayList<StreamItemEntry> mStreamItems;
         private final HashMap<Long, DataStatus> mStatuses;
+        private final ArrayList<String> mInvitableAccountTypes;
 
         private String mDirectoryDisplayName;
         private String mDirectoryType;
@@ -147,6 +149,7 @@
             mPhoneticName = null;
             mStarred = false;
             mPresence = null;
+            mInvitableAccountTypes = null;
         }
 
         /**
@@ -173,6 +176,7 @@
             mPhoneticName = phoneticName;
             mStarred = starred;
             mPresence = presence;
+            mInvitableAccountTypes = Lists.newArrayList();
         }
 
         private Result(Result from) {
@@ -193,6 +197,7 @@
             mEntities = from.mEntities;
             mStreamItems = from.mStreamItems;
             mStatuses = from.mStatuses;
+            mInvitableAccountTypes = from.mInvitableAccountTypes;
 
             mDirectoryDisplayName = from.mDirectoryDisplayName;
             mDirectoryType = from.mDirectoryType;
@@ -279,6 +284,10 @@
             return mPresence;
         }
 
+        public ArrayList<String> getInvitableAccontTypes() {
+            return mInvitableAccountTypes;
+        }
+
         public ArrayList<Entity> getEntities() {
             return mEntities;
         }
@@ -568,6 +577,9 @@
                         loadStreamItems(result);
                     }
                     loadPhotoBinaryData(result);
+                    if (mLoadInvitableAccountTypes) {
+                        loadInvitableAccountTypes(result);
+                    }
                 }
                 return result;
             } catch (Exception e) {
@@ -718,6 +730,27 @@
             }
         }
 
+        private void loadInvitableAccountTypes(Result contactData) {
+            Map<String, AccountType> allInvitables =
+                    AccountTypeManager.getInstance(getContext()).getInvitableAccountTypes();
+            if (allInvitables.isEmpty()) {
+                return;
+            }
+
+            HashMap<String, AccountType> result = new HashMap<String, AccountType>(allInvitables);
+
+            // Remove the ones that already has a raw contact in the current contact
+            for (Entity entity : contactData.getEntities()) {
+                final String type = entity.getEntityValues().getAsString(RawContacts.ACCOUNT_TYPE);
+                if (!TextUtils.isEmpty(type)) {
+                    result.remove(type);
+                }
+            }
+
+            // Set to mInvitableAccountTypes
+            contactData.mInvitableAccountTypes.addAll(result.keySet());
+        }
+
         /**
          * Extracts Contact level columns from the cursor.
          */
@@ -1058,15 +1091,16 @@
     }
 
     public ContactLoader(Context context, Uri lookupUri) {
-        this(context, lookupUri, false, false);
+        this(context, lookupUri, false, false, false);
     }
 
     public ContactLoader(Context context, Uri lookupUri, boolean loadGroupMetaData,
-            boolean loadStreamItems) {
+            boolean loadStreamItems, boolean loadInvitableAccountTypes) {
         super(context);
         mLookupUri = lookupUri;
         mLoadGroupMetaData = loadGroupMetaData;
         mLoadStreamItems = loadStreamItems;
+        mLoadInvitableAccountTypes = loadInvitableAccountTypes;
     }
 
     public Uri getLookupUri() {
diff --git a/src/com/android/contacts/ContactOptionsActivity.java b/src/com/android/contacts/ContactOptionsActivity.java
index 9ae8fe9..dd7387f 100644
--- a/src/com/android/contacts/ContactOptionsActivity.java
+++ b/src/com/android/contacts/ContactOptionsActivity.java
@@ -16,6 +16,8 @@
 
 package com.android.contacts;
 
+import com.android.contacts.activities.PeopleActivity;
+
 import android.app.ActionBar;
 import android.app.Activity;
 import android.content.ContentValues;
@@ -221,6 +223,9 @@
 
         switch (item.getItemId()) {
             case android.R.id.home:
+                Intent intent = new Intent(this, PeopleActivity.class);
+                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                startActivity(intent);
                 finish();
                 return true;
             default:
diff --git a/src/com/android/contacts/GroupListLoader.java b/src/com/android/contacts/GroupListLoader.java
new file mode 100644
index 0000000..49aa602
--- /dev/null
+++ b/src/com/android/contacts/GroupListLoader.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.contacts;
+
+import android.content.Context;
+import android.content.CursorLoader;
+import android.provider.ContactsContract.Groups;
+
+/**
+ * Group loader for the group list that includes details such as the number of contacts per group.
+ * This group list excludes default, favorite, and deleted groups.
+ */
+public final class GroupListLoader extends CursorLoader {
+
+    private final static String[] COLUMNS = new String[] {
+        Groups.ACCOUNT_NAME,
+        Groups.ACCOUNT_TYPE,
+        Groups._ID,
+        Groups.TITLE,
+        Groups.ACTION,
+        Groups.ACTION_URI,
+        Groups.SUMMARY_COUNT,
+    };
+
+    public final static int ACCOUNT_NAME = 0;
+    public final static int ACCOUNT_TYPE = 1;
+    public final static int GROUP_ID = 2;
+    public final static int TITLE = 3;
+    public final static int ACTION = 4;
+    public final static int ACTION_URI = 5;
+    public final static int MEMBER_COUNT = 6;
+
+    public GroupListLoader(Context context) {
+        super(context, Groups.CONTENT_SUMMARY_URI, COLUMNS, Groups.ACCOUNT_TYPE + " NOT NULL AND "
+                + Groups.ACCOUNT_NAME + " NOT NULL AND " + Groups.AUTO_ADD + "=0 AND " +
+                Groups.FAVORITES + "=0 AND " + Groups.DELETED + "=0", null,
+                Groups.ACCOUNT_NAME + " ASC");
+    }
+}
diff --git a/src/com/android/contacts/PhoneCallDetailsHelper.java b/src/com/android/contacts/PhoneCallDetailsHelper.java
index b2810bc..019e608 100644
--- a/src/com/android/contacts/PhoneCallDetailsHelper.java
+++ b/src/com/android/contacts/PhoneCallDetailsHelper.java
@@ -20,7 +20,6 @@
 import com.android.contacts.calllog.PhoneNumberHelper;
 import com.android.contacts.format.FormatUtils;
 
-import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Typeface;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
@@ -29,7 +28,6 @@
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.view.View;
-import android.widget.ImageView;
 
 /**
  * Helper class to fill in the views in {@link PhoneCallDetailsViews}.
@@ -38,7 +36,6 @@
     /** The maximum number of icons will be shown to represent the call types in a group. */
     private static final int MAX_CALL_TYPE_ICONS = 3;
 
-    private final Context mContext;
     private final Resources mResources;
     /** The injected current time in milliseconds since the epoch. Used only by tests. */
     private Long mCurrentTimeMillisForTest;
@@ -53,9 +50,8 @@
      *
      * @param resources used to look up strings
      */
-    public PhoneCallDetailsHelper(Context context, Resources resources,
-            CallTypeHelper callTypeHelper, PhoneNumberHelper phoneNumberHelper) {
-        mContext = context;
+    public PhoneCallDetailsHelper(Resources resources, CallTypeHelper callTypeHelper,
+            PhoneNumberHelper phoneNumberHelper) {
         mResources = resources;
         mCallTypeHelper = callTypeHelper;
         mPhoneNumberHelper = phoneNumberHelper;
@@ -63,15 +59,12 @@
 
     /** Fills the call details views with content. */
     public void setPhoneCallDetails(PhoneCallDetailsViews views, PhoneCallDetails details,
-            boolean useIcons, boolean isHighlighted) {
+            boolean useIcons, boolean isHighlighted, boolean nameOnly) {
         if (useIcons) {
             views.callTypeIcons.removeAllViews();
             int count = details.callTypes.length;
             for (int index = 0; index < count && index < MAX_CALL_TYPE_ICONS; ++index) {
-                int callType = details.callTypes[index];
-                ImageView callTypeImage = new ImageView(mContext);
-                callTypeImage.setImageDrawable(mCallTypeHelper.getCallTypeDrawable(callType));
-                views.callTypeIcons.addView(callTypeImage);
+                mCallTypeHelper.inflateCallTypeIcon(details.callTypes[index], views.callTypeIcons);
             }
             views.callTypeIcons.setVisibility(View.VISIBLE);
             if (count > MAX_CALL_TYPE_ICONS) {
@@ -144,6 +137,10 @@
         } else {
             views.numberView.setVisibility(View.GONE);
         }
+
+        // Hide the rest if not visible.
+        views.callTypeView.setVisibility(nameOnly ? View.GONE : View.VISIBLE);
+        views.numberView.setVisibility(nameOnly ? View.GONE : View.VISIBLE);
     }
 
     public void setCurrentTimeForTest(long currentTimeMillis) {
diff --git a/src/com/android/contacts/PhoneCallDetailsViews.java b/src/com/android/contacts/PhoneCallDetailsViews.java
index 7453af0..19e931f 100644
--- a/src/com/android/contacts/PhoneCallDetailsViews.java
+++ b/src/com/android/contacts/PhoneCallDetailsViews.java
@@ -16,6 +16,7 @@
 
 package com.android.contacts;
 
+import android.content.Context;
 import android.view.View;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -25,15 +26,17 @@
  */
 public final class PhoneCallDetailsViews {
     public final TextView nameView;
+    public final View callTypeView;
     public final LinearLayout callTypeIcons;
     public final TextView callTypeText;
     public final View callTypeSeparator;
     public final TextView dateView;
     public final TextView numberView;
 
-    private PhoneCallDetailsViews(TextView nameView, LinearLayout callTypeIcons,
+    private PhoneCallDetailsViews(TextView nameView, View callTypeView, LinearLayout callTypeIcons,
             TextView callTypeText, View callTypeSeparator, TextView dateView, TextView numberView) {
         this.nameView = nameView;
+        this.callTypeView = callTypeView;
         this.callTypeIcons = callTypeIcons;
         this.callTypeText = callTypeText;
         this.callTypeSeparator = callTypeSeparator;
@@ -50,6 +53,7 @@
      */
     public static PhoneCallDetailsViews fromView(View view) {
         return new PhoneCallDetailsViews((TextView) view.findViewById(R.id.name),
+                view.findViewById(R.id.call_type),
                 (LinearLayout) view.findViewById(R.id.call_type_icons),
                 (TextView) view.findViewById(R.id.call_type_name),
                 view.findViewById(R.id.call_type_separator),
@@ -57,10 +61,14 @@
                 (TextView) view.findViewById(R.id.number));
     }
 
-    public static PhoneCallDetailsViews createForTest(TextView nameView,
-            LinearLayout callTypeIcons, TextView callTypeText, View callTypeSeparator,
-            TextView dateView, TextView numberView) {
-        return new PhoneCallDetailsViews(nameView, callTypeIcons, callTypeText, callTypeSeparator,
-                dateView, numberView);
+    public static PhoneCallDetailsViews createForTest(Context context) {
+        return new PhoneCallDetailsViews(
+                new TextView(context),
+                new View(context),
+                new LinearLayout(context),
+                new TextView(context),
+                new View(context),
+                new TextView(context),
+                new TextView(context));
     }
 }
diff --git a/src/com/android/contacts/activities/ContactDetailActivity.java b/src/com/android/contacts/activities/ContactDetailActivity.java
index 4d04ac2..a31694f 100644
--- a/src/com/android/contacts/activities/ContactDetailActivity.java
+++ b/src/com/android/contacts/activities/ContactDetailActivity.java
@@ -161,11 +161,6 @@
             mDetailFragment.setListener(mFragmentListener);
             mDetailFragment.setVerticalScrollListener(mVerticalScrollListener);
             mDetailFragment.setData(mLookupUri, mContactData);
-            // If the contact has social updates, then the photo should be shown in the tab
-            // carousel, so don't show the photo again in the scrolling list of contact details.
-            // We also don't want to show the photo if there is a fragment carousel because then
-            // the picture will already be on the left of the list of contact details.
-            mDetailFragment.setShowPhotoInHeader(!mContactHasUpdates && mFragmentCarousel == null);
         } else if (fragment instanceof ContactDetailUpdatesFragment) {
             mUpdatesFragment = (ContactDetailUpdatesFragment) fragment;
             mUpdatesFragment.setData(mLookupUri, mContactData);
@@ -531,6 +526,9 @@
 
         switch (item.getItemId()) {
             case android.R.id.home:
+                Intent intent = new Intent(this, PeopleActivity.class);
+                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                startActivity(intent);
                 finish();
                 return true;
             default:
diff --git a/src/com/android/contacts/activities/GroupDetailActivity.java b/src/com/android/contacts/activities/GroupDetailActivity.java
index 9f6aa90..c7cf47c 100644
--- a/src/com/android/contacts/activities/GroupDetailActivity.java
+++ b/src/com/android/contacts/activities/GroupDetailActivity.java
@@ -146,6 +146,9 @@
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
             case android.R.id.home:
+                Intent intent = new Intent(this, PeopleActivity.class);
+                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                startActivity(intent);
                 finish();
                 return true;
             default:
diff --git a/src/com/android/contacts/calllog/CallDetailHistoryAdapter.java b/src/com/android/contacts/calllog/CallDetailHistoryAdapter.java
index ae81a79..e55020c 100644
--- a/src/com/android/contacts/calllog/CallDetailHistoryAdapter.java
+++ b/src/com/android/contacts/calllog/CallDetailHistoryAdapter.java
@@ -26,7 +26,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
-import android.widget.ImageView;
+import android.widget.FrameLayout;
 import android.widget.TextView;
 
 /**
@@ -69,13 +69,14 @@
         }
 
         PhoneCallDetails details = mPhoneCallDetails[position];
-        ImageView callTypeIconView = (ImageView) convertView.findViewById(R.id.call_type_icon);
+        FrameLayout callTypeIconView = (FrameLayout) convertView.findViewById(R.id.call_type_icon);
         TextView callTypeTextView = (TextView) convertView.findViewById(R.id.call_type_text);
         TextView dateView = (TextView) convertView.findViewById(R.id.date);
         TextView durationView = (TextView) convertView.findViewById(R.id.duration);
 
         int callType = details.callTypes[0];
-        callTypeIconView.setImageDrawable(mCallTypeHelper.getCallTypeDrawable(callType));
+        callTypeIconView.removeAllViews();
+        mCallTypeHelper.inflateCallTypeIcon(callType, callTypeIconView);
         callTypeTextView.setText(mCallTypeHelper.getCallTypeText(callType));
         // Set the date.
         CharSequence dateValue = DateUtils.formatDateRange(mContext, details.date, details.date,
diff --git a/src/com/android/contacts/calllog/CallLogFragment.java b/src/com/android/contacts/calllog/CallLogFragment.java
index 9f64815..3f3fd8d 100644
--- a/src/com/android/contacts/calllog/CallLogFragment.java
+++ b/src/com/android/contacts/calllog/CallLogFragment.java
@@ -63,7 +63,6 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.widget.ListView;
-import android.widget.QuickContactBadge;
 import android.widget.TextView;
 
 import java.util.LinkedList;
@@ -72,7 +71,8 @@
 /**
  * Displays a list of call log entries.
  */
-public class CallLogFragment extends ListFragment implements ViewPagerVisibilityListener {
+public class CallLogFragment extends ListFragment implements ViewPagerVisibilityListener,
+        CallLogQueryHandler.Listener {
     private static final String TAG = "CallLogFragment";
 
     /** The size of the cache of contact info. */
@@ -175,7 +175,7 @@
     private TextView mStatusMessageAction;
 
     public static final class ContactInfo {
-        public long personId;
+        public long personId = -1;
         public String name;
         public int type;
         public String label;
@@ -312,11 +312,8 @@
             mPreDrawListener = null;
 
             Resources resources = getResources();
-            CallTypeHelper callTypeHelper = new CallTypeHelper(resources,
-                    resources.getDrawable(R.drawable.ic_call_incoming_holo_dark),
-                    resources.getDrawable(R.drawable.ic_call_outgoing_holo_dark),
-                    resources.getDrawable(R.drawable.ic_call_missed_holo_dark),
-                    resources.getDrawable(R.drawable.ic_call_voicemail_holo_dark));
+            LayoutInflater layoutInflater = getActivity().getLayoutInflater();
+            CallTypeHelper callTypeHelper = new CallTypeHelper(resources, layoutInflater);
             Drawable callDrawable = resources.getDrawable(R.drawable.ic_dial_action_call);
             Drawable playDrawable = resources.getDrawable(
                     R.drawable.ic_call_log_list_action_play);
@@ -324,7 +321,7 @@
             mContactPhotoManager = ContactPhotoManager.getInstance(getActivity());
             mPhoneNumberHelper = new PhoneNumberHelper(getResources(), mVoiceMailNumber);
             PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper(
-                    getActivity(), resources, callTypeHelper, mPhoneNumberHelper);
+                    resources, callTypeHelper, mPhoneNumberHelper);
             mCallLogViewsHelper =
                     new CallLogListItemHelper(phoneCallDetailsHelper, mPhoneNumberHelper);
             mCallLogGroupBuilder = new CallLogGroupBuilder(this);
@@ -659,7 +656,8 @@
             // Get the views to bind to.
             CallLogListItemViews views = CallLogListItemViews.fromView(view);
             views.callView.setOnClickListener(this);
-            views.playView.setOnClickListener(this);
+            // Do nothing when a plain photo is clicked. Without this, the list item will fire.
+            views.plainPhotoView.setOnClickListener(null);
             view.setTag(views);
         }
 
@@ -697,21 +695,18 @@
             final String formattedNumber;
             final String countryIso = c.getString(CallLogQuery.COUNTRY_ISO);
 
-            // Store away the number so we can call it directly if you click on the call icon.
-            if (!TextUtils.isEmpty(number)) {
-                views.callView.setTag(IntentProvider.getReturnCallIntentProvider(number));
-            } else {
-                views.callView.setTag(null);
-            }
-
             // Store away the voicemail information so we can play it directly.
             if (callType == Calls.VOICEMAIL_TYPE) {
                 String voicemailUri = c.getString(CallLogQuery.VOICEMAIL_URI);
                 final long rowId = c.getLong(CallLogQuery.ID);
-                views.playView.setTag(
+                views.callView.setTag(
                         IntentProvider.getPlayVoicemailIntentProvider(rowId, voicemailUri));
+            } else if (!TextUtils.isEmpty(number)) {
+                // Store away the number so we can call it directly if you click on the call icon.
+                views.callView.setTag(IntentProvider.getReturnCallIntentProvider(number));
             } else {
-                views.playView.setTag(null);
+                // No action enabled.
+                views.callView.setTag(null);
             }
 
             // Lookup contacts with this number
@@ -769,10 +764,7 @@
             // New items also use the highlighted version of the text.
             final boolean isHighlighted = isNew;
             mCallLogViewsHelper.setPhoneCallDetails(views, details, useIcons, isHighlighted);
-            if (views.photoView != null) {
-                bindQuickContact(views.photoView, thumbnailUri, personId, lookupKey);
-            }
-
+            setPhoto(views, thumbnailUri, personId, lookupKey);
 
             // Listen for the first draw
             if (mPreDrawListener == null) {
@@ -800,14 +792,20 @@
             return callTypes;
         }
 
-        private void bindQuickContact(QuickContactBadge view, Uri thumbnailUri, long contactId,
+        private void setPhoto(CallLogListItemViews views, Uri thumbnailUri, long contactId,
                 String lookupKey) {
-            view.assignContactUri(getContactUri(contactId, lookupKey));
-            mContactPhotoManager.loadPhoto(view, thumbnailUri);
-        }
-
-        private Uri getContactUri(long contactId, String lookupKey) {
-            return Contacts.getLookupUri(contactId, lookupKey);
+            if (contactId == -1) {
+                // This does not correspond to a contact, do not use the QuickContactBadge.
+                mContactPhotoManager.loadPhoto(views.plainPhotoView, thumbnailUri);
+                views.plainPhotoView.setVisibility(View.VISIBLE);
+                views.quickContactView.setVisibility(View.GONE);
+            } else {
+                views.quickContactView.assignContactUri(
+                        Contacts.getLookupUri(contactId, lookupKey));
+                mContactPhotoManager.loadPhoto(views.quickContactView, thumbnailUri);
+                views.quickContactView.setVisibility(View.VISIBLE);
+                views.plainPhotoView.setVisibility(View.GONE);
+            }
         }
 
         /**
@@ -836,7 +834,7 @@
 
         mVoiceMailNumber = ((TelephonyManager) getActivity().getSystemService(
                 Context.TELEPHONY_SERVICE)).getVoiceMailNumber();
-        mCallLogQueryHandler = new CallLogQueryHandler(this);
+        mCallLogQueryHandler = new CallLogQueryHandler(getActivity().getContentResolver(), this);
 
         mCurrentCountryIso = ContactsUtils.getCurrentCountryIso(getActivity());
 
@@ -844,6 +842,7 @@
     }
 
     /** Called by the CallLogQueryHandler when the list of calls has been fetched or updated. */
+    @Override
     public void onCallsFetched(Cursor cursor) {
         if (getActivity() == null || getActivity().isFinishing()) {
             return;
@@ -863,6 +862,7 @@
     /**
      * Called by {@link CallLogQueryHandler} after a successful query to voicemail status provider.
      */
+    @Override
     public void onVoicemailStatusFetched(Cursor statusCursor) {
         if (getActivity() == null || getActivity().isFinishing()) {
             return;
@@ -1099,12 +1099,12 @@
 
     @Override
     public void onListItemClick(ListView l, View v, int position, long id) {
-        Intent intent = new Intent(getActivity(), CallDetailActivity.class);
         Cursor cursor = (Cursor) mAdapter.getItem(position);
         if (CallLogQuery.isSectionHeader(cursor)) {
             // Do nothing when a header is clicked.
             return;
         }
+        Intent intent = new Intent(getActivity(), CallDetailActivity.class);
         if (mAdapter.isGroupHeader(position)) {
             // We want to restore the position in the cursor at the end.
             int currentPosition = cursor.getPosition();
diff --git a/src/com/android/contacts/calllog/CallLogListItemHelper.java b/src/com/android/contacts/calllog/CallLogListItemHelper.java
index d4f2291..d8184d2 100644
--- a/src/com/android/contacts/calllog/CallLogListItemHelper.java
+++ b/src/com/android/contacts/calllog/CallLogListItemHelper.java
@@ -54,19 +54,27 @@
     public void setPhoneCallDetails(CallLogListItemViews views, PhoneCallDetails details,
             boolean useIcons, boolean isHighlighted) {
         mPhoneCallDetailsHelper.setPhoneCallDetails(views.phoneCallDetailsViews, details, useIcons,
-                isHighlighted);
-        boolean callVisible = mPhoneNumberHelper.canPlaceCallsTo(details.number);
-        boolean playVisible = details.callTypes[0] == Calls.VOICEMAIL_TYPE;
+                isHighlighted, false);
+        boolean canCall = mPhoneNumberHelper.canPlaceCallsTo(details.number);
+        boolean canPlay = details.callTypes[0] == Calls.VOICEMAIL_TYPE;
 
-        if (callVisible || playVisible) {
-            // At least one is visible. Keep the divider and the space for the call button.
-            views.callView.setVisibility(callVisible ? View.VISIBLE : View.INVISIBLE);
-            views.playView.setVisibility(playVisible ? View.VISIBLE : View.GONE);
+        if (canPlay) {
+            // Playback action takes preference.
+            views.callView.setVisibility(View.GONE);
+            views.playView.setVisibility(View.VISIBLE);
+            views.unheardView.setVisibility(isHighlighted ? View.VISIBLE : View.GONE);
+            views.dividerView.setVisibility(View.VISIBLE);
+        } else if (canCall) {
+            // Call is the main action.
+            views.callView.setVisibility(View.VISIBLE);
+            views.playView.setVisibility(View.GONE);
+            views.unheardView.setVisibility(View.GONE);
             views.dividerView.setVisibility(View.VISIBLE);
         } else {
-            // Neither is visible, remove all of them entirely.
+            // No action available.
             views.callView.setVisibility(View.GONE);
             views.playView.setVisibility(View.GONE);
+            views.unheardView.setVisibility(View.GONE);
             views.dividerView.setVisibility(View.GONE);
         }
     }
diff --git a/src/com/android/contacts/calllog/CallLogListItemViews.java b/src/com/android/contacts/calllog/CallLogListItemViews.java
index b66d84e..90f78f7 100644
--- a/src/com/android/contacts/calllog/CallLogListItemViews.java
+++ b/src/com/android/contacts/calllog/CallLogListItemViews.java
@@ -19,6 +19,7 @@
 import com.android.contacts.PhoneCallDetailsViews;
 import com.android.contacts.R;
 
+import android.content.Context;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.QuickContactBadge;
@@ -28,12 +29,16 @@
  * Simple value object containing the various views within a call log entry.
  */
 public final class CallLogListItemViews {
-    /** The quick contact badge for the contact. Only present for group and stand alone entries. */
-    public final QuickContactBadge photoView;
+    /** The quick contact badge for the contact. */
+    public final QuickContactBadge quickContactView;
+    /** The photo view without quick contact badge. */
+    public final ImageView plainPhotoView;
     /** The main action button on the entry. */
-    public final ImageView callView;
+    public final View callView;
     /** The play action button used for voicemail. */
-    public final ImageView playView;
+    public final View playView;
+    /** The icon used for unheard voicemail. */
+    public final View unheardView;
     /** The divider between callView and playView. */
     public final View dividerView;
     /** The details of the phone call. */
@@ -45,12 +50,15 @@
     /** The text of the header in a stand-alone row, or null for other types of rows. */
     public final TextView listHeaderTextView;
 
-    private CallLogListItemViews(QuickContactBadge photoView, ImageView callView,
-            ImageView playView, View dividerView, PhoneCallDetailsViews phoneCallDetailsViews,
-            View listItemView, View listHeaderView, TextView listHeaderTextView) {
-        this.photoView = photoView;
+    private CallLogListItemViews(QuickContactBadge quickContactView, ImageView photoView,
+            View callView, View playView, View unheardView, View dividerView,
+            PhoneCallDetailsViews phoneCallDetailsViews, View listItemView, View listHeaderView,
+            TextView listHeaderTextView) {
+        this.quickContactView = quickContactView;
+        this.plainPhotoView = photoView;
         this.callView = callView;
         this.playView = playView;
+        this.unheardView = unheardView;
         this.dividerView = dividerView;
         this.phoneCallDetailsViews = phoneCallDetailsViews;
         this.listItemView = listItemView;
@@ -59,9 +67,12 @@
     }
 
     public static CallLogListItemViews fromView(View view) {
-        return new CallLogListItemViews((QuickContactBadge) view.findViewById(R.id.contact_photo),
-                (ImageView) view.findViewById(R.id.call_icon),
-                (ImageView) view.findViewById(R.id.play_icon),
+        return new CallLogListItemViews(
+                (QuickContactBadge) view.findViewById(R.id.quick_contact_photo),
+                (ImageView) view.findViewById(R.id.plain_contact_photo),
+                view.findViewById(R.id.call_icon),
+                view.findViewById(R.id.play_icon),
+                view.findViewById(R.id.unheard_icon),
                 view.findViewById(R.id.divider),
                 PhoneCallDetailsViews.fromView(view),
                 view.findViewById(R.id.call_log_item),
@@ -69,12 +80,17 @@
                 (TextView) view.findViewById(R.id.call_log_header_text));
     }
 
-    public static CallLogListItemViews createForTest(QuickContactBadge photoView,
-            ImageView callView, ImageView playView, View dividerView,
-            PhoneCallDetailsViews phoneCallDetailsViews, View standAloneItemView,
-            View standAloneHeaderView, TextView standAloneHeaderTextView) {
-        return new CallLogListItemViews(photoView, callView, playView, dividerView,
-                phoneCallDetailsViews, standAloneItemView, standAloneHeaderView,
-                standAloneHeaderTextView);
+    public static CallLogListItemViews createForTest(Context context) {
+        return new CallLogListItemViews(
+                new QuickContactBadge(context),
+                new ImageView(context),
+                new View(context),
+                new View(context),
+                new View(context),
+                new View(context),
+                PhoneCallDetailsViews.createForTest(context),
+                new View(context),
+                new View(context),
+                new TextView(context));
     }
 }
diff --git a/src/com/android/contacts/calllog/CallLogQueryHandler.java b/src/com/android/contacts/calllog/CallLogQueryHandler.java
index fdf55b9..d2905c1 100644
--- a/src/com/android/contacts/calllog/CallLogQueryHandler.java
+++ b/src/com/android/contacts/calllog/CallLogQueryHandler.java
@@ -21,6 +21,7 @@
 import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
 
 import android.content.AsyncQueryHandler;
+import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.database.MatrixCursor;
@@ -54,7 +55,7 @@
     /** The token for the query to fetch voicemail status messages. */
     private static final int QUERY_VOICEMAIL_STATUS_TOKEN = 56;
 
-    private final WeakReference<CallLogFragment> mFragment;
+    private final WeakReference<Listener> mListener;
 
     /** The cursor containing the new calls, or null if they have not yet been fetched. */
     @GuardedBy("this") private Cursor mNewCallsCursor;
@@ -91,9 +92,9 @@
         return new CatchingWorkerHandler(looper);
     }
 
-    public CallLogQueryHandler(CallLogFragment fragment) {
-        super(fragment.getActivity().getContentResolver());
-        mFragment = new WeakReference<CallLogFragment>(fragment);
+    public CallLogQueryHandler(ContentResolver contentResolver, Listener listener) {
+        super(contentResolver);
+        mListener = new WeakReference<Listener>(listener);
     }
 
     /** Creates a cursor that contains a single row and maps the section to the given value. */
@@ -268,16 +269,28 @@
      * Updates the adapter in the call log fragment to show the new cursor data.
      */
     private void updateAdapterData(Cursor combinedCursor) {
-        final CallLogFragment fragment = mFragment.get();
-        if (fragment != null) {
-            fragment.onCallsFetched(combinedCursor);
+        final Listener listener = mListener.get();
+        if (listener != null) {
+            listener.onCallsFetched(combinedCursor);
         }
     }
 
     private void updateVoicemailStatus(Cursor statusCursor) {
-        final CallLogFragment fragment = mFragment.get();
-        if (fragment != null) {
-            fragment.onVoicemailStatusFetched(statusCursor);
+        final Listener listener = mListener.get();
+        if (listener != null) {
+            listener.onVoicemailStatusFetched(statusCursor);
         }
     }
-}
\ No newline at end of file
+
+    /** Listener to completion of various queries. */
+    public interface Listener {
+        /** Called when {@link CallLogQueryHandler#fetchVoicemailStatus()} completes. */
+        void onVoicemailStatusFetched(Cursor statusCursor);
+
+        /**
+         * Called when {@link CallLogQueryHandler#fetchAllCalls()} or
+         * {@link CallLogQueryHandler#fetchVoicemailOnly()} complete.
+         */
+        void onCallsFetched(Cursor combinedCursor);
+    }
+}
diff --git a/src/com/android/contacts/calllog/CallTypeHelper.java b/src/com/android/contacts/calllog/CallTypeHelper.java
index 0c2068e..465e2bf 100644
--- a/src/com/android/contacts/calllog/CallTypeHelper.java
+++ b/src/com/android/contacts/calllog/CallTypeHelper.java
@@ -20,25 +20,21 @@
 
 import android.content.res.Resources;
 import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
 import android.provider.CallLog.Calls;
 import android.text.SpannableString;
 import android.text.Spanned;
 import android.text.style.ForegroundColorSpan;
 import android.text.style.StyleSpan;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
 
 /**
  * Helper class to perform operations related to call types.
  */
 public class CallTypeHelper {
-    /** Icon for incoming calls. */
-    private final Drawable mIncomingDrawable;
-    /** Icon for outgoing calls. */
-    private final Drawable mOutgoingDrawable;
-    /** Icon for missed calls. */
-    private final Drawable mMissedDrawable;
-    /** Icon for voicemails. */
-    private final Drawable mVoicemailDrawable;
+    /** Used to create the views for the call types. */
+    private final LayoutInflater mLayoutInflater;
     /** Name used to identify incoming calls. */
     private final CharSequence mIncomingName;
     /** Name used to identify outgoing calls. */
@@ -52,12 +48,8 @@
     /** Name used to identify new voicemail calls. */
     private final CharSequence mNewVoicemailName;
 
-    public CallTypeHelper(Resources resources, Drawable incomingDrawable, Drawable outgoingDrawable,
-            Drawable missedDrawable, Drawable voicemailDrawable) {
-        mIncomingDrawable = incomingDrawable;
-        mOutgoingDrawable = outgoingDrawable;
-        mMissedDrawable = missedDrawable;
-        mVoicemailDrawable = voicemailDrawable;
+    public CallTypeHelper(Resources resources, LayoutInflater layoutInflater) {
+        mLayoutInflater = layoutInflater;
         // Cache these values so that we do not need to look them up each time.
         mIncomingName = resources.getString(R.string.type_incoming);
         mOutgoingName = resources.getString(R.string.type_outgoing);
@@ -111,20 +103,20 @@
         }
     }
 
-    /** Returns the drawable of the icon associated with the given call type. */
-    public Drawable getCallTypeDrawable(int callType) {
+    /** Returns a new view for the icon to be used to represent a given call type. */
+    public View inflateCallTypeIcon(int callType, ViewGroup root) {
         switch (callType) {
             case Calls.INCOMING_TYPE:
-                return mIncomingDrawable;
+                return mLayoutInflater.inflate(R.layout.call_log_incoming_call_icon, root);
 
             case Calls.OUTGOING_TYPE:
-                return mOutgoingDrawable;
+                return mLayoutInflater.inflate(R.layout.call_log_outgoing_call_icon, root);
 
             case Calls.MISSED_TYPE:
-                return mMissedDrawable;
+                return mLayoutInflater.inflate(R.layout.call_log_missed_call_icon, root);
 
             case Calls.VOICEMAIL_TYPE:
-                return mVoicemailDrawable;
+                return mLayoutInflater.inflate(R.layout.call_log_voicemail_icon, root);
 
             default:
                 throw new IllegalArgumentException("invalid call type: " + callType);
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index 9709480..17df4b4 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -129,7 +129,7 @@
 
     private ContactLoader.Result mContactData;
     private ViewGroup mHeaderView;
-    private ImageView mPhotoView;
+    private ImageView mStaticPhotoView;
     private ListView mListView;
     private ViewAdapter mAdapter;
     private Uri mPrimaryPhoneUri = null;
@@ -140,8 +140,8 @@
     private final ArrayList<Long> mWritableRawContactIds = new ArrayList<Long>();
     private int mNumPhoneNumbers = 0;
     private String mDefaultCountryIso;
-    private boolean mContactDataDisplayed;
-    private boolean mContactPhotoDisplayedInHeader = true;
+    private boolean mContactHasSocialUpdates;
+    private boolean mShowStaticPhoto = true;
 
     private final QuickFix[] mPotentialQuickFixes = new QuickFix[] {
             new MakeLocalCopyQuickFix(),
@@ -248,7 +248,7 @@
 
         mInflater = inflater;
 
-        mPhotoView = (ImageView) mView.findViewById(R.id.photo);
+        mStaticPhotoView = (ImageView) mView.findViewById(R.id.photo);
 
         mListView = (ListView) mView.findViewById(android.R.id.list);
         mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY);
@@ -336,11 +336,11 @@
     }
 
     /**
-     * Sets whether or not the contact photo should be shown in the list of contact details in this
-     * {@link Fragment}.
+     * Sets whether the static contact photo (that is not in a scrolling region), should be shown
+     * or not.
      */
-    public void setShowPhotoInHeader(boolean showPhoto) {
-        mContactPhotoDisplayedInHeader = showPhoto;
+    public void setShowStaticPhoto(boolean showPhoto) {
+        mShowStaticPhoto = showPhoto;
     }
 
     public void setData(Uri lookupUri, ContactLoader.Result result) {
@@ -371,9 +371,21 @@
         // Clear old header
         mHeaderView = null;
 
+        // Figure out if the contact has social updates or not
+        mContactHasSocialUpdates = !mContactData.getStreamItems().isEmpty();
+
         // Setup the photo if applicable
-        if (mPhotoView != null) {
-            ContactDetailDisplayUtils.setPhoto(mContext, mContactData, mPhotoView);
+        if (mStaticPhotoView != null) {
+            // The presence of a static photo view is not sufficient to determine whether or not
+            // we should show the photo. Check the mShowStaticPhoto flag which can be set by an
+            // outside class depending on screen size, layout, and whether the contact has social
+            // updates or not.
+            if (mShowStaticPhoto) {
+                mStaticPhotoView.setVisibility(View.VISIBLE);
+                ContactDetailDisplayUtils.setPhoto(mContext, mContactData, mStaticPhotoView);
+            } else {
+                mStaticPhotoView.setVisibility(View.GONE);
+            }
         }
 
         // Build up the contact entries
@@ -1073,14 +1085,12 @@
                 entry.typeString = "";
                 for (EditType type : kind.typeList) {
                     if (type.rawValue == entry.type) {
-                        if (!type.unspecifiedType) {
-                            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);
-                            }
+                        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);
                         }
                         break;
                     }
@@ -1261,26 +1271,21 @@
                 return mHeaderView;
             }
 
-            mHeaderView = (ViewGroup) inflate(
-                    R.layout.simple_contact_detail_header_view_list_item, parent, false);
+            int resourceId = mContactHasSocialUpdates ?
+                    R.layout.detail_header_contact_with_updates :
+                    R.layout.detail_header_contact_without_updates;
+            mHeaderView = (ViewGroup) inflate(resourceId, parent, false);
 
             TextView displayNameView = (TextView) mHeaderView.findViewById(R.id.name);
             TextView companyView = (TextView) mHeaderView.findViewById(R.id.company);
-            TextView phoneticNameView = (TextView) mHeaderView.findViewById(R.id.phonetic_name);
-            TextView attributionView = (TextView) mHeaderView.findViewById(R.id.attribution);
             ImageView photoView = (ImageView) mHeaderView.findViewById(R.id.photo);
 
             ContactDetailDisplayUtils.setDisplayName(mContext, mContactData, displayNameView);
             ContactDetailDisplayUtils.setCompanyName(mContext, mContactData, companyView);
-            ContactDetailDisplayUtils.setPhoneticName(mContext, mContactData, phoneticNameView);
-            ContactDetailDisplayUtils.setAttribution(mContext, mContactData, attributionView);
 
             // Set the photo if it should be displayed
-            if (mContactPhotoDisplayedInHeader) {
+            if (photoView != null) {
                 ContactDetailDisplayUtils.setPhoto(mContext, mContactData, photoView);
-            } else {
-                // Otherwise hide the view
-                photoView.setVisibility(View.INVISIBLE);
             }
 
             // Set the starred state if it should be displayed
diff --git a/src/com/android/contacts/detail/ContactDetailLayoutController.java b/src/com/android/contacts/detail/ContactDetailLayoutController.java
index d93edea..d912670 100644
--- a/src/com/android/contacts/detail/ContactDetailLayoutController.java
+++ b/src/com/android/contacts/detail/ContactDetailLayoutController.java
@@ -137,7 +137,9 @@
 
         switch (mLayoutMode) {
             case TWO_COLUMN: {
-                // Set the contact data
+                // Set the contact data (hide the static photo because the photo will already be in
+                // the header that scrolls with contact details).
+                mContactDetailFragment.setShowStaticPhoto(false);
                 mContactDetailFragment.setData(mContactData.getLookupUri(), mContactData);
                 mContactDetailUpdatesFragment.setData(mContactData.getLookupUri(), mContactData);
 
@@ -175,6 +177,7 @@
 
         switch (mLayoutMode) {
             case TWO_COLUMN:
+                mContactDetailFragment.setShowStaticPhoto(true);
                 mContactDetailFragment.setData(mContactData.getLookupUri(), mContactData);
                 ft.hide(mContactDetailUpdatesFragment);
                 break;
@@ -227,7 +230,6 @@
                     }
                     mPagerContactDetailFragment.setListener(mContactDetailFragmentListener);
                     mPagerContactDetailFragment.setVerticalScrollListener(mVerticalScrollListener);
-                    mPagerContactDetailFragment.setShowPhotoInHeader(false);
                     return mPagerContactDetailFragment;
                 case 1:
                     mPagerContactDetailUpdatesFragment = new ContactDetailUpdatesFragment();
diff --git a/src/com/android/contacts/detail/ContactLoaderFragment.java b/src/com/android/contacts/detail/ContactLoaderFragment.java
index 034a8cc..daa6012 100644
--- a/src/com/android/contacts/detail/ContactLoaderFragment.java
+++ b/src/com/android/contacts/detail/ContactLoaderFragment.java
@@ -171,7 +171,7 @@
         public Loader<ContactLoader.Result> onCreateLoader(int id, Bundle args) {
             Uri lookupUri = args.getParcelable(LOADER_ARG_CONTACT_URI);
             return new ContactLoader(mContext, lookupUri, true /* loadGroupMetaData */,
-                    true /* loadStreamItems */);
+                    true /* loadStreamItems */, false /* load invitable account types */);
         }
 
         @Override
diff --git a/src/com/android/contacts/editor/ExternalRawContactEditorView.java b/src/com/android/contacts/editor/ExternalRawContactEditorView.java
index 89cace0..e1a669b 100644
--- a/src/com/android/contacts/editor/ExternalRawContactEditorView.java
+++ b/src/com/android/contacts/editor/ExternalRawContactEditorView.java
@@ -164,7 +164,7 @@
         mName.setText(primary.getAsString(StructuredName.DISPLAY_NAME));
 
         if (type.readOnly) {
-            mReadOnlyWarning.setText(mContext.getString(R.string.contact_read_only, accountType));
+            mReadOnlyWarning.setText(mContext.getString(R.string.contact_read_only));
             mReadOnlyWarning.setVisibility(View.VISIBLE);
             mEditExternallyButton.setVisibility(View.GONE);
         } else {
diff --git a/src/com/android/contacts/group/GroupBrowseListAdapter.java b/src/com/android/contacts/group/GroupBrowseListAdapter.java
index 2dd194d..d44733b 100644
--- a/src/com/android/contacts/group/GroupBrowseListAdapter.java
+++ b/src/com/android/contacts/group/GroupBrowseListAdapter.java
@@ -16,28 +16,22 @@
 
 package com.android.contacts.group;
 
-import com.android.contacts.GroupMetaData;
+import com.android.contacts.GroupListLoader;
 import com.android.contacts.R;
 import com.android.contacts.model.AccountType;
 import com.android.contacts.model.AccountTypeManager;
 
-import android.accounts.Account;
 import android.content.ContentUris;
 import android.content.Context;
+import android.database.Cursor;
 import android.net.Uri;
 import android.provider.ContactsContract.Groups;
-import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
-import android.widget.LinearLayout;
 import android.widget.TextView;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
 /**
  * Adapter to populate the list of groups.
  */
@@ -47,49 +41,36 @@
     private final LayoutInflater mLayoutInflater;
     private final AccountTypeManager mAccountTypeManager;
 
-    private List<GroupListEntry> mGroupList = new ArrayList<GroupListEntry>();
+    private Cursor mCursor;
+
     private boolean mSelectionVisible;
     private Uri mSelectedGroupUri;
 
-    enum ViewType {
-        HEADER, ITEM;
-    }
-
-    private static final int VIEW_TYPE_COUNT = ViewType.values().length;
-
-    public GroupBrowseListAdapter(Context context, Map<Account, List<GroupMetaData>> groupMap) {
+    public GroupBrowseListAdapter(Context context) {
         mContext = context;
         mLayoutInflater = LayoutInflater.from(context);
         mAccountTypeManager = AccountTypeManager.getInstance(mContext);
+    }
 
-        for (Account account : groupMap.keySet()) {
-            List<GroupMetaData> groupsListForAccount = groupMap.get(account);
-
-            // Add account name, type, and # of groups as header for section
-            mGroupList.add(GroupListEntry.createEntryForHeader(account.name, account.type,
-                    groupsListForAccount.size()));
-
-            // Add groups within that account as subsequent list items.
-            for (GroupMetaData singleGroup : groupsListForAccount) {
-                mGroupList.add(GroupListEntry.createEntryForGroup(singleGroup));
-            }
-        }
+    public void setCursor(Cursor cursor) {
+        mCursor = cursor;
+        notifyDataSetChanged();
     }
 
     public int getSelectedGroupPosition() {
-        if (mSelectedGroupUri == null) {
+        if (mSelectedGroupUri == null || mCursor == null || mCursor.getCount() == 0) {
             return -1;
         }
 
-        int size = mGroupList.size();
-        for (int i = 0; i < size; i++) {
-            GroupListEntry group = mGroupList.get(i);
-            if (group.type == ViewType.ITEM) {
-                Uri uri = getGroupUriFromId(group.groupData.getGroupId());
-                if (mSelectedGroupUri.equals(uri)) {
-                    return i;
-                }
+        int index = 0;
+        mCursor.moveToPosition(-1);
+        while (mCursor.moveToNext()) {
+            long groupId = mCursor.getLong(GroupListLoader.GROUP_ID);
+            Uri uri = getGroupUriFromId(groupId);
+            if (mSelectedGroupUri.equals(uri)) {
+                  return index;
             }
+            index++;
         }
         return -1;
     }
@@ -108,163 +89,123 @@
 
     @Override
     public int getCount() {
-        return mGroupList.size();
+        return mCursor == null ? 0 : mCursor.getCount();
     }
 
     @Override
     public long getItemId(int position) {
-        return mGroupList.get(position).id;
+        return position;
     }
 
     @Override
-    public GroupListEntry getItem(int position) {
-        return mGroupList.get(position);
-    }
+    public GroupListItem getItem(int position) {
+        if (mCursor == null || mCursor.isClosed() || !mCursor.moveToPosition(position)) {
+            return null;
+        }
+        String accountName = mCursor.getString(GroupListLoader.ACCOUNT_NAME);
+        String accountType = mCursor.getString(GroupListLoader.ACCOUNT_TYPE);
+        long groupId = mCursor.getLong(GroupListLoader.GROUP_ID);
+        String title = mCursor.getString(GroupListLoader.TITLE);
+        int memberCount = mCursor.getInt(GroupListLoader.MEMBER_COUNT);
 
-    @Override
-    public int getItemViewType(int position) {
-        return mGroupList.get(position).type.ordinal();
-    }
+        // Figure out if this is the first group for this account name / account type pair by
+        // checking the previous entry. This is to determine whether or not we need to display an
+        // account header in this item.
+        int previousIndex = position - 1;
+        boolean isFirstGroupInAccount = true;
+        if (previousIndex >= 0 && mCursor.moveToPosition(previousIndex)) {
+            String previousGroupAccountName = mCursor.getString(GroupListLoader.ACCOUNT_NAME);
+            String previousGroupAccountType = mCursor.getString(GroupListLoader.ACCOUNT_TYPE);
+            if (accountName.equals(previousGroupAccountName) &&
+                    accountType.equals(previousGroupAccountType)) {
+                isFirstGroupInAccount = false;
+            }
+        }
 
-    @Override
-    public int getViewTypeCount() {
-        return VIEW_TYPE_COUNT;
-    }
-
-    @Override
-    public boolean areAllItemsEnabled() {
-        return false;
-    }
-
-    @Override
-    public boolean isEnabled(int position) {
-        return mGroupList.get(position).type == ViewType.ITEM;
+        return new GroupListItem(accountName, accountType, groupId, title, isFirstGroupInAccount,
+                memberCount);
     }
 
     @Override
     public View getView(int position, View convertView, ViewGroup parent) {
-        GroupListEntry item = getItem(position);
-        switch (item.type) {
-            case HEADER:
-                return getHeaderView(item, convertView, parent);
-            case ITEM:
-                return getGroupListItemView(item, convertView, parent);
-            default:
-                throw new IllegalStateException("Invalid GroupListEntry item type " + item.type);
+        GroupListItem entry = getItem(position);
+        View result;
+        GroupListItemViewCache viewCache;
+        if (convertView != null) {
+            result = convertView;
+            viewCache = (GroupListItemViewCache) result.getTag();
+        } else {
+            result = mLayoutInflater.inflate(R.layout.group_browse_list_item, parent, false);
+            viewCache = new GroupListItemViewCache(result);
+            result.setTag(viewCache);
         }
 
-    }
+        // Add a header if this is the first group in an account and hide the divider
+        if (entry.isFirstGroupInAccount()) {
+            bindHeaderView(entry, viewCache);
+            viewCache.accountHeader.setVisibility(View.VISIBLE);
+            viewCache.divider.setVisibility(View.GONE);
+        } else {
+            viewCache.accountHeader.setVisibility(View.GONE);
+            viewCache.divider.setVisibility(View.VISIBLE);
+        }
 
-    private View getHeaderView(GroupListEntry entry, View convertView, ViewGroup parent) {
-        View result = (convertView == null ?
-                mLayoutInflater.inflate(R.layout.group_list_header_item, parent, false) :
-                convertView);
+        // Bind the group data
+        Uri groupUri = getGroupUriFromId(entry.getGroupId());
+        String memberCountString = mContext.getResources().getQuantityString(
+                R.plurals.group_list_num_contacts_in_group, entry.getMemberCount(),
+                entry.getMemberCount());
+        viewCache.setUri(groupUri);
+        viewCache.groupTitle.setText(entry.getTitle());
+        viewCache.groupMemberCount.setText(memberCountString);
 
-        TextView accountTypeTextView = (TextView) result.findViewById(R.id.account_type);
-        AccountType accountType = mAccountTypeManager.getAccountType(entry.accountType);
-        accountTypeTextView.setText(accountType.getDisplayLabel(mContext).toString().toUpperCase());
-
-        TextView accountNameTextView = (TextView) result.findViewById(R.id.account_name);
-        accountNameTextView.setText(entry.accountName);
-
-        String groupCountString = mContext.getResources().getQuantityString(
-                R.plurals.num_groups_in_account, entry.count, entry.count);
-        TextView groupCountTextView = (TextView) result.findViewById(R.id.group_count);
-        groupCountTextView.setText(groupCountString);
-
-        return result;
-    }
-
-    private View getGroupListItemView(GroupListEntry entry, View convertView, ViewGroup parent) {
-        GroupListItem result = (GroupListItem) (convertView == null ?
-                mLayoutInflater.inflate(R.layout.group_browse_list_item, parent, false) :
-                convertView);
-        result.loadFromGroup(entry.groupData);
         if (mSelectionVisible) {
-            result.setActivated(isSelectedGroup(result.getUri()));
+            result.setActivated(isSelectedGroup(groupUri));
         }
         return result;
     }
 
-    /**
-     * This is a data model object to represent one row in the list of groups were the entry
-     * could be a header or group item.
-     */
-    public static class GroupListEntry {
-        public final ViewType type;
-        public final String accountType;
-        public final String accountName;
-        public final int count;
-        public final GroupMetaData groupData;
-        /**
-         * The id is equal to the group ID (if groupData is available), otherwise it is -1 for
-         * header entries.
-         */
-        public final long id;
+    private void bindHeaderView(GroupListItem entry, GroupListItemViewCache viewCache) {
+        AccountType accountType = mAccountTypeManager.getAccountType(entry.getAccountType());
+        viewCache.accountType.setText(accountType.getDisplayLabel(mContext).toString());
+        viewCache.accountName.setText(entry.getAccountName());
 
-        private GroupListEntry(ViewType entryType, String groupAccountName, String groupAccountType,
-                int headerGroupCount, GroupMetaData groupMetaData, long entryId) {
-            type = entryType;
-            accountName = groupAccountName;
-            accountType = groupAccountType;
-            count = headerGroupCount;
-            groupData = groupMetaData;
-            id = entryId;
-        }
+        // TODO: Add in number of groups within this account name / type using this string:
+        // getQuantityString(R.plurals.num_groups_in_account, entry.count, entry.count);
+    }
 
-        public static GroupListEntry createEntryForHeader(String groupAccountName,
-                String groupAccountType, int groupCount) {
-            return new GroupListEntry(ViewType.HEADER, groupAccountName, groupAccountType,
-                    groupCount, null, -1);
-        }
-
-        public static GroupListEntry createEntryForGroup(GroupMetaData groupMetaData) {
-            if (groupMetaData == null) {
-                throw new IllegalStateException("Cannot create list entry for a null group");
-            }
-            return new GroupListEntry(ViewType.ITEM, null, null, 0, groupMetaData,
-                    groupMetaData.getGroupId());
-        }
+    private static Uri getGroupUriFromId(long groupId) {
+        return ContentUris.withAppendedId(Groups.CONTENT_URI, groupId);
     }
 
     /**
-     * A row in a list of groups, where this row displays a single group's title
-     * and associated account.
+     * Cache of the children views of a contact detail entry represented by a
+     * {@link GroupListItem}
      */
-    public static class GroupListItem extends LinearLayout {
-
-        private TextView mLabel;
+    public static class GroupListItemViewCache {
+        public final TextView accountType;
+        public final TextView accountName;
+        public final TextView groupTitle;
+        public final TextView groupMemberCount;
+        public final View accountHeader;
+        public final View divider;
         private Uri mUri;
 
-        public GroupListItem(Context context, AttributeSet attrs, int defStyle) {
-            super(context, attrs, defStyle);
+        public GroupListItemViewCache(View view) {
+            accountType = (TextView) view.findViewById(R.id.account_type);
+            accountName = (TextView) view.findViewById(R.id.account_name);
+            groupTitle = (TextView) view.findViewById(R.id.label);
+            groupMemberCount = (TextView) view.findViewById(R.id.count);
+            accountHeader = view.findViewById(R.id.group_list_header);
+            divider = view.findViewById(R.id.divider);
         }
 
-        public GroupListItem(Context context, AttributeSet attrs) {
-            super(context, attrs);
-        }
-
-        public GroupListItem(Context context) {
-            super(context);
-        }
-
-        @Override
-        protected void onFinishInflate() {
-            super.onFinishInflate();
-            mLabel = (TextView) findViewById(R.id.label);
-        }
-
-        public void loadFromGroup(GroupMetaData group) {
-            mLabel.setText(group.getTitle());
-            mUri = getGroupUriFromId(group.getGroupId());
+        public void setUri(Uri uri) {
+            mUri = uri;
         }
 
         public Uri getUri() {
             return mUri;
         }
     }
-
-    private static Uri getGroupUriFromId(long groupId) {
-        return ContentUris.withAppendedId(Groups.CONTENT_URI, groupId);
-    }
 }
\ 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 4e6bdbc..d0d370e 100644
--- a/src/com/android/contacts/group/GroupBrowseListFragment.java
+++ b/src/com/android/contacts/group/GroupBrowseListFragment.java
@@ -16,13 +16,11 @@
 
 package com.android.contacts.group;
 
-import com.android.contacts.GroupMetaData;
-import com.android.contacts.GroupMetaDataLoader;
+import com.android.contacts.GroupListLoader;
 import com.android.contacts.R;
-import com.android.contacts.group.GroupBrowseListAdapter.GroupListItem;
+import com.android.contacts.group.GroupBrowseListAdapter.GroupListItemViewCache;
 import com.android.contacts.widget.AutoScrollListView;
 
-import android.accounts.Account;
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.LoaderManager;
@@ -34,7 +32,6 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Parcelable;
-import android.provider.ContactsContract.Groups;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -47,11 +44,6 @@
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.ListView;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 /**
  * Fragment to display the list of groups.
  */
@@ -82,13 +74,6 @@
 
     private static final String EXTRA_KEY_GROUP_URI = "groups.groupUri";
 
-    /**
-     * Map of {@link Account} to a list of {@link GroupMetaData} objects
-     * representing groups within that account.
-     */
-    private final Map<Account, List<GroupMetaData>> mGroupMap =
-            new HashMap<Account, List<GroupMetaData>>();
-
     private View mRootView;
     private AutoScrollListView mListView;
     private View mEmptyView;
@@ -108,10 +93,25 @@
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
         mRootView = inflater.inflate(R.layout.group_browse_list_fragment, null);
+        mEmptyView = mRootView.findViewById(R.id.empty);
+
+        mAdapter = new GroupBrowseListAdapter(mContext);
+        mAdapter.setSelectionVisible(mSelectionVisible);
+        mAdapter.setSelectedGroup(mSelectedGroupUri);
+
         mListView = (AutoScrollListView) mRootView.findViewById(R.id.list);
         mListView.setOnFocusChangeListener(this);
         mListView.setOnTouchListener(this);
-        mEmptyView = mRootView.findViewById(R.id.empty);
+        mListView.setAdapter(mAdapter);
+        mListView.setOnItemClickListener(new OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                GroupListItemViewCache groupListItem = (GroupListItemViewCache) view.getTag();
+                if (groupListItem != null) {
+                    viewGroup(groupListItem.getUri());
+                }
+            }
+        });
 
         if (savedInstanceState != null) {
             String groupUriString = savedInstanceState.getString(EXTRA_KEY_GROUP_URI);
@@ -173,7 +173,7 @@
 
         @Override
         public CursorLoader onCreateLoader(int id, Bundle args) {
-            return new GroupMetaDataLoader(mContext, Groups.CONTENT_URI);
+            return new GroupListLoader(mContext);
         }
 
         @Override
@@ -190,64 +190,16 @@
         if (mGroupListCursor == null) {
             return;
         }
-        mGroupMap.clear();
-        mGroupListCursor.moveToPosition(-1);
-        while (mGroupListCursor.moveToNext()) {
-            String accountName = mGroupListCursor.getString(GroupMetaDataLoader.ACCOUNT_NAME);
-            String accountType = mGroupListCursor.getString(GroupMetaDataLoader.ACCOUNT_TYPE);
-            long groupId = mGroupListCursor.getLong(GroupMetaDataLoader.GROUP_ID);
-            String title = mGroupListCursor.getString(GroupMetaDataLoader.TITLE);
-            boolean deleted =
-                    (mGroupListCursor.getInt(GroupMetaDataLoader.DELETED) == 1);
-            boolean defaultGroup = mGroupListCursor.isNull(GroupMetaDataLoader.AUTO_ADD)
-                    ? false
-                    : mGroupListCursor.getInt(GroupMetaDataLoader.AUTO_ADD) != 0;
-            boolean favorites = mGroupListCursor.isNull(GroupMetaDataLoader.FAVORITES)
-                    ? false
-                    : mGroupListCursor.getInt(GroupMetaDataLoader.FAVORITES) != 0;
-
-            // Don't show the "auto-added" (i.e. My Contacts) or "favorites" groups because
-            // they show up elsewhere in the app. Also skip groups that are marked as "deleted"
-            if (defaultGroup || favorites || deleted) {
-                continue;
-            }
-
-            GroupMetaData newGroup = new GroupMetaData(accountName, accountType, groupId, title,
-                    defaultGroup, favorites);
-            Account account = new Account(accountName, accountType);
-
-            if (mGroupMap.containsKey(account)) {
-                List<GroupMetaData> groups = mGroupMap.get(account);
-                groups.add(newGroup);
-            } else {
-                List<GroupMetaData> groups = new ArrayList<GroupMetaData>();
-                groups.add(newGroup);
-                mGroupMap.put(account, groups);
-            }
-
-        }
-
-        mAdapter = new GroupBrowseListAdapter(mContext, mGroupMap);
-        mAdapter.setSelectionVisible(mSelectionVisible);
-        mAdapter.setSelectedGroup(mSelectedGroupUri);
+        mAdapter.setCursor(mGroupListCursor);
 
         Parcelable listState = mListView.onSaveInstanceState();
-        mListView.setAdapter(mAdapter);
-        mListView.setEmptyView(mEmptyView);
-        mListView.setOnItemClickListener(new OnItemClickListener() {
-            @Override
-            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-                GroupListItem groupListItem = (GroupListItem) view;
-                viewGroup(groupListItem.getUri());
-            }
-        });
-
         if (mSelectionToScreenRequested) {
             requestSelectionToScreen();
         } else {
             // Restore the scroll position.
             mListView.onRestoreInstanceState(listState);
         }
+        mListView.setEmptyView(mEmptyView);
 
         if (mSelectionVisible && mSelectedGroupUri != null) {
             viewGroup(mSelectedGroupUri);
@@ -260,6 +212,9 @@
 
     public void setSelectionVisible(boolean flag) {
         mSelectionVisible = flag;
+        if (mAdapter != null) {
+            mAdapter.setSelectionVisible(mSelectionVisible);
+        }
     }
 
     private void setSelectedGroup(Uri groupUri) {
diff --git a/src/com/android/contacts/group/GroupListItem.java b/src/com/android/contacts/group/GroupListItem.java
new file mode 100644
index 0000000..4740c44
--- /dev/null
+++ b/src/com/android/contacts/group/GroupListItem.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.contacts.group;
+
+/**
+ * Meta-data for a contact group.  We load all groups associated with the contact's
+ * constituent accounts.
+ */
+public final class GroupListItem {
+    private final String mAccountName;
+    private final String mAccountType;
+    private final long mGroupId;
+    private final String mTitle;
+    private final boolean mIsFirstGroupInAccount;
+    private final int mMemberCount;
+
+    public GroupListItem(String accountName, String accountType, long groupId, String title,
+            boolean isFirstGroupInAccount, int memberCount) {
+        this.mAccountName = accountName;
+        this.mAccountType = accountType;
+        this.mGroupId = groupId;
+        this.mTitle = title;
+        this.mIsFirstGroupInAccount = isFirstGroupInAccount;
+        this.mMemberCount = memberCount;
+    }
+
+    public String getAccountName() {
+        return mAccountName;
+    }
+
+    public String getAccountType() {
+        return mAccountType;
+    }
+
+    public long getGroupId() {
+        return mGroupId;
+    }
+
+    public String getTitle() {
+        return mTitle;
+    }
+
+    public int getMemberCount() {
+        return mMemberCount;
+    }
+
+    public boolean hasMemberCount() {
+        return mMemberCount != -1;
+    }
+
+    public boolean isFirstGroupInAccount() {
+        return mIsFirstGroupInAccount;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/contacts/list/AccountFilterActivity.java b/src/com/android/contacts/list/AccountFilterActivity.java
index c38599e..24eab23 100644
--- a/src/com/android/contacts/list/AccountFilterActivity.java
+++ b/src/com/android/contacts/list/AccountFilterActivity.java
@@ -19,6 +19,7 @@
 import com.android.contacts.ContactsActivity;
 import com.android.contacts.ContactsSearchManager;
 import com.android.contacts.R;
+import com.android.contacts.activities.PeopleActivity;
 import com.android.contacts.model.AccountType;
 import com.android.contacts.model.AccountTypeManager;
 
@@ -167,6 +168,9 @@
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
             case android.R.id.home:
+                Intent intent = new Intent(this, PeopleActivity.class);
+                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                startActivity(intent);
                 finish();
                 return true;
             default:
diff --git a/src/com/android/contacts/list/ContactListItemView.java b/src/com/android/contacts/list/ContactListItemView.java
index d69f880..4c20dca 100644
--- a/src/com/android/contacts/list/ContactListItemView.java
+++ b/src/com/android/contacts/list/ContactListItemView.java
@@ -667,9 +667,6 @@
         }
         if (mQuickContact == null) {
             mQuickContact = new QuickContactBadge(mContext, null, QUICK_CONTACT_BADGE_STYLE);
-            mQuickContact.setExcludeMimes(new String[] {
-                Contacts.CONTENT_ITEM_TYPE
-            });
             addView(mQuickContact);
             mPhotoViewWidthAndHeightAreReady = false;
         }
diff --git a/src/com/android/contacts/model/AccountType.java b/src/com/android/contacts/model/AccountType.java
index 70aa430..608fca3 100644
--- a/src/com/android/contacts/model/AccountType.java
+++ b/src/com/android/contacts/model/AccountType.java
@@ -33,6 +33,7 @@
 import android.provider.ContactsContract.RawContacts;
 import android.widget.EditText;
 
+import java.text.Collator;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -120,7 +121,7 @@
      */
     public CharSequence getInviteContactActionLabel(Context context) {
         return getResourceText(context, summaryResPackageName, getInviteContactActionResId(context),
-                null);
+                "");
     }
 
     /**
@@ -218,11 +219,6 @@
         public int specificMax;
         public String customColumn;
 
-        /**
-         * True if this type may be shown as blank.
-         */
-        public boolean unspecifiedType;
-
         public EditType(int rawValue, int labelRes) {
             this.rawValue = rawValue;
             this.labelRes = labelRes;
@@ -244,11 +240,6 @@
             return this;
         }
 
-        public EditType setUnspecifiedType(boolean unspecifiedType) {
-            this.unspecifiedType = unspecifiedType;
-            return this;
-        }
-
         @Override
         public boolean equals(Object object) {
             if (object instanceof EditType) {
@@ -342,4 +333,28 @@
         public CharSequence inflateUsing(Context context, Cursor cursor);
         public CharSequence inflateUsing(Context context, ContentValues values);
     }
+
+    /**
+     * Compare two {@link AccountType} by their {@link AccountType#getDisplayLabel} with the
+     * current locale.
+     */
+    public static class DisplayLabelComparator implements Comparator<AccountType> {
+        private final Context mContext;
+        /** {@link Comparator} for the current locale. */
+        private final Collator mCollator = Collator.getInstance();
+
+        public DisplayLabelComparator(Context context) {
+            mContext = context;
+        }
+
+        private String getDisplayLabel(AccountType type) {
+            CharSequence label = type.getDisplayLabel(mContext);
+            return (label == null) ? "" : label.toString();
+        }
+
+        @Override
+        public int compare(AccountType lhs, AccountType rhs) {
+            return mCollator.compare(getDisplayLabel(lhs), getDisplayLabel(rhs));
+        }
+    }
 }
diff --git a/src/com/android/contacts/model/BaseAccountType.java b/src/com/android/contacts/model/BaseAccountType.java
index 547a488..06cb039 100644
--- a/src/com/android/contacts/model/BaseAccountType.java
+++ b/src/com/android/contacts/model/BaseAccountType.java
@@ -69,28 +69,23 @@
     }
 
     protected EditType buildPhoneType(int type) {
-        return new EditType(type, Phone.getTypeLabelResource(type))
-                .setUnspecifiedType(type == Phone.TYPE_OTHER);
+        return new EditType(type, Phone.getTypeLabelResource(type));
     }
 
     protected EditType buildEmailType(int type) {
-        return new EditType(type, Email.getTypeLabelResource(type))
-                .setUnspecifiedType(type == Email.TYPE_OTHER);
+        return new EditType(type, Email.getTypeLabelResource(type));
     }
 
     protected EditType buildPostalType(int type) {
-        return new EditType(type, StructuredPostal.getTypeLabelResource(type))
-                .setUnspecifiedType(type == StructuredPostal.TYPE_OTHER);
+        return new EditType(type, StructuredPostal.getTypeLabelResource(type));
     }
 
     protected EditType buildImType(int type) {
-        return new EditType(type, Im.getProtocolLabelResource(type))
-                .setUnspecifiedType(type == Im.TYPE_OTHER);
+        return new EditType(type, Im.getProtocolLabelResource(type));
     }
 
     protected EditType buildEventType(int type, boolean yearOptional) {
-        return new EventEditType(type, Event.getTypeResource(type)).setYearOptional(yearOptional)
-                .setUnspecifiedType(type == Event.TYPE_OTHER);
+        return new EventEditType(type, Event.getTypeResource(type)).setYearOptional(yearOptional);
     }
 
     protected EditType buildRelationType(int type) {
diff --git a/src/com/android/contacts/socialwidget/SocialWidgetProvider.java b/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
index d59aebd..3d7881b 100644
--- a/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
+++ b/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
@@ -111,7 +111,8 @@
             // Not yet set-up (this can happen while the Configuration activity is visible)
             return;
         }
-        final ContactLoader contactLoader = new ContactLoader(context, contactUri, false, true);
+        final ContactLoader contactLoader = new ContactLoader(context, contactUri, false, true,
+                false);
         contactLoader.registerListener(0,
                 new ContactLoader.OnLoadCompleteListener<ContactLoader.Result>() {
                     @Override
diff --git a/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java b/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
index 436f13b..b1da1a1 100644
--- a/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
+++ b/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
@@ -37,7 +37,9 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
 
+import javax.annotation.concurrent.GuardedBy;
 import javax.annotation.concurrent.NotThreadSafe;
 
 /**
@@ -64,6 +66,7 @@
     private TextView mPlaybackPositionText;
     private ImageButton mRateDecreaseButton;
     private ImageButton mRateIncreaseButton;
+    private TextViewWithMessagesController mTextController;
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -77,6 +80,7 @@
         mPlaybackPositionText = (TextView) view.findViewById(R.id.playback_position_text);
         mRateDecreaseButton = (ImageButton) view.findViewById(R.id.rate_decrease_button);
         mRateIncreaseButton = (ImageButton) view.findViewById(R.id.rate_increase_button);
+        mTextController = new TextViewWithMessagesController(mPlaybackPositionText);
         return view;
     }
 
@@ -173,12 +177,9 @@
         }
 
         @Override
-        public void setRateDisplay(float rate) {
-            // TODO: This isn't being done yet.  Old rate display code has been removed.
-            // Instead we're going to temporarily fade out the track position when you change
-            // rate, and display one of the words "slowest", "slower", "normal", "faster",
-            // "fastest" briefly when you change speed, before fading back in the time.
-            // At least, that's the current thinking.
+        public void setRateDisplay(float rate, int stringResourceId) {
+            mTextController.setTemporaryText(
+                    getActivity().getString(stringResourceId), 1, TimeUnit.SECONDS);
         }
 
         @Override
@@ -202,16 +203,15 @@
         }
 
         @Override
-        public void setClipLength(int clipLengthInMillis) {
-            mPlaybackSeek.setMax(clipLengthInMillis);
-            // TODO: The old code used to set the static lenght-of-clip text field, but now
-            // the thinking is that we will only show this text whilst the recording is stopped.
-        }
-
-        @Override
-        public void setClipPosition(int clipPositionInMillis) {
-            mPlaybackSeek.setProgress(clipPositionInMillis);
-            mPlaybackPositionText.setText(formatAsMinutesAndSeconds(clipPositionInMillis));
+        public void setClipPosition(int clipPositionInMillis, int clipLengthInMillis) {
+            int seekBarPosition = Math.max(0, clipPositionInMillis);
+            int seekBarMax = Math.max(seekBarPosition, clipLengthInMillis);
+            if (mPlaybackSeek.getMax() != seekBarMax) {
+                mPlaybackSeek.setMax(seekBarMax);
+            }
+            mPlaybackSeek.setProgress(seekBarPosition);
+            mTextController.setPermanentText(
+                    formatAsMinutesAndSeconds(seekBarMax - seekBarPosition));
         }
 
         @Override
@@ -246,4 +246,61 @@
             }
         }
     }
+
+    /**
+     * Controls a TextView with dynamically changing text.
+     * <p>
+     * There are two methods here of interest,
+     * {@link TextViewWithMessagesController#setPermanentText(String)} and
+     * {@link TextViewWithMessagesController#setTemporaryText(String, long, TimeUnit)}.  The
+     * former is used to set the text on the text view immediately, and is used in our case for
+     * the countdown of duration remaining during voicemail playback.  The second is used to
+     * temporarily replace this countdown with a message, in our case faster voicemail speed or
+     * slower voicemail speed, before returning to the countdown display.
+     * <p>
+     * All the methods on this class must be called from the ui thread.
+     */
+    private static final class TextViewWithMessagesController {
+        private final Object mLock = new Object();
+        private final TextView mTextView;
+        @GuardedBy("mLock") String mCurrentText = "";
+        @GuardedBy("mLock") Runnable mRunnable;
+
+        public TextViewWithMessagesController(TextView textView) {
+            mTextView = textView;
+        }
+
+        public void setPermanentText(String text) {
+            synchronized (mLock) {
+                mCurrentText = text;
+                // If there's currently a Runnable pending, then we don't alter the display
+                // text. The Runnable will use the most recent version of mCurrentText
+                // when it completes.
+                if (mRunnable == null) {
+                    mTextView.setText(text);
+                }
+            }
+        }
+
+        public void setTemporaryText(String text, long duration, TimeUnit units) {
+            synchronized (mLock) {
+                mTextView.setText(text);
+                mRunnable = new Runnable() {
+                    @Override
+                    public void run() {
+                        synchronized (mLock) {
+                            // We check for (mRunnable == this) becuase if not true, then another
+                            // setTemporaryText call has taken place in the meantime, and this
+                            // one is now defunct and needs to take no action.
+                            if (mRunnable == this) {
+                                mRunnable = null;
+                                mTextView.setText(mCurrentText);
+                            }
+                        }
+                    }
+                };
+                mTextView.postDelayed(mRunnable, units.toMillis(duration));
+            }
+        }
+    }
 }
diff --git a/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java b/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
index 53e64e9..5e7b707 100644
--- a/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
+++ b/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
@@ -16,6 +16,7 @@
 
 package com.android.contacts.voicemail;
 
+import com.android.contacts.R;
 import com.android.ex.variablespeed.MediaPlayerProxy;
 import com.android.ex.variablespeed.SingleThreadedMediaPlayerProxy;
 
@@ -56,8 +57,7 @@
         void setPositionSeekListener(SeekBar.OnSeekBarChangeListener listener);
         void setSpeakerphoneListener(View.OnClickListener listener);
         void setDeleteButtonListener(View.OnClickListener listener);
-        void setClipLength(int clipLengthInMillis);
-        void setClipPosition(int clipPositionInMillis);
+        void setClipPosition(int clipPositionInMillis, int clipLengthInMillis);
         int getDesiredClipPosition();
         void playbackStarted();
         void playbackStopped();
@@ -65,7 +65,7 @@
         boolean isSpeakerPhoneOn();
         void setSpeakerPhoneOn(boolean on);
         void finish();
-        void setRateDisplay(float rate);
+        void setRateDisplay(float rate, int stringResourceId);
         void setRateIncreaseButtonListener(View.OnClickListener listener);
         void setRateDecreaseButtonListener(View.OnClickListener listener);
     }
@@ -89,9 +89,31 @@
     private static final float[] PRESET_RATES = new float[] {
         0.64f, 0.8f, 1.0f, 1.25f, 1.5625f
     };
+    /** The string resource ids corresponding to the names given to the above preset rates. */
+    private static final int[] PRESET_NAMES = new int[] {
+        R.string.voicemail_speed_slowest,
+        R.string.voicemail_speed_slower,
+        R.string.voicemail_speed_normal,
+        R.string.voicemail_speed_faster,
+        R.string.voicemail_speed_fastest,
+    };
+    /**
+     * Pointer into the {@link VoicemailPlaybackPresenter#PRESET_RATES} array.
+     * <p>
+     * This doesn't need to be synchronized, it's used only by the {@link RateChangeListener}
+     * which in turn is only executed on the ui thread.  This can't be encapsulated inside the
+     * rate change listener since multiple rate change listeners must share the same value.
+     */
+    private int mRateIndex = 2;
 
-    /** Index into {@link #PRESET_RATES} indicating the current playback speed. */
-    private final AtomicInteger mCurrentPlaybackRate = new AtomicInteger(2);
+    /**
+     * The most recently calculated duration.
+     * <p>
+     * We cache this in a field since we don't want to keep requesting it from the player, as
+     * this can easily lead to throwing {@link IllegalStateException} (any time the player is
+     * released, it's illegal to ask for the duration).
+     */
+    private final AtomicInteger mDuration = new AtomicInteger(0);
 
     private final PlaybackView mView;
     private final MediaPlayerProxy mPlayer;
@@ -117,7 +139,7 @@
         mView.setSpeakerPhoneOn(mView.isSpeakerPhoneOn());
         mView.setRateDecreaseButtonListener(createRateDecreaseListener());
         mView.setRateIncreaseButtonListener(createRateIncreaseListener());
-        mView.setClipPosition(0);
+        mView.setClipPosition(0, 0);
         mView.playbackStopped();
         // TODO: Now I'm ignoring the bundle, when previously I was checking for contains against
         // the PAUSED_STATE_KEY, and CLIP_POSITION_KEY.
@@ -131,6 +153,7 @@
     }
 
     public void onDestroy() {
+        mPositionUpdater.stopUpdating();
         mPlayer.release();
     }
 
@@ -174,6 +197,11 @@
         return new RateChangeListener(true);
     }
 
+    /**
+     * Listens to clicks on the rate increase and decrease buttons.
+     * <p>
+     * This class is not thread-safe, but all interactions with it will happen on the ui thread.
+     */
     private class RateChangeListener implements View.OnClickListener {
         private final boolean mIncrease;
 
@@ -183,33 +211,32 @@
 
         @Override
         public void onClick(View v) {
-            int adjustment = (mIncrease ? 1 : -1);
-            int andGet = mCurrentPlaybackRate.addAndGet(adjustment);
-            if (andGet < 0) {
-                // TODO: discussions with interaction design have suggested that we might make
-                // an audible tone play here to indicate that you've hit the end of the range?
-                // Let's firm up this decision.
-                mCurrentPlaybackRate.set(0);
-            } else if (andGet >= PRESET_RATES.length) {
-                mCurrentPlaybackRate.set(PRESET_RATES.length - 1);
-            } else {
-                changeRate(PRESET_RATES[andGet]);
-            }
+            // Adjust the current rate, then clamp it to the allowed values.
+            mRateIndex = clamp(mRateIndex + (mIncrease ? 1 : -1), 0, PRESET_RATES.length - 1);
+            // Whether or not we have actually changed the index, call changeRate().
+            // This will ensure that we show the "fastest" or "slowest" text on the ui to indicate
+            // to the user that it doesn't get any faster or slower.
+            changeRate(PRESET_RATES[mRateIndex], PRESET_NAMES[mRateIndex]);
         }
     }
 
+    /** Clamp the input value to between min and max inclusive. */
+    private static int clamp(int input, int min, int max) {
+        return Math.max(Math.min(input, max), min);
+    }
+
     private void resetPrepareStartPlaying(int clipPositionInMillis) {
         try {
             mPlayer.reset();
             mPlayer.setDataSource(mView.getDataSourceContext(), mVoicemailUri);
             mPlayer.prepare();
-            int clipLengthInMillis = mPlayer.getDuration();
-            mView.setClipLength(clipLengthInMillis);
-            int startPosition = Math.min(Math.max(clipPositionInMillis, 0), clipLengthInMillis);
+            mDuration.set(mPlayer.getDuration());
+            int startPosition = clamp(clipPositionInMillis, 0, mDuration.get());
+            mView.setClipPosition(startPosition, mDuration.get());
             mPlayer.seekTo(startPosition);
             mPlayer.start();
             mView.playbackStarted();
-            mPositionUpdater.startUpdating(startPosition, clipLengthInMillis);
+            mPositionUpdater.startUpdating(startPosition, mDuration.get());
         } catch (IOException e) {
             handleError(e);
         }
@@ -217,18 +244,18 @@
 
     private void handleError(Exception e) {
         mView.playbackError(e);
-        mPlayer.release();
         mPositionUpdater.stopUpdating();
+        mPlayer.release();
     }
 
     public void handleCompletion(MediaPlayer mediaPlayer) {
-        stopPlaybackAtPosition(0);
+        stopPlaybackAtPosition(0, mDuration.get());
     }
 
-    private void stopPlaybackAtPosition(int clipPosition) {
-        mView.playbackStopped();
+    private void stopPlaybackAtPosition(int clipPosition, int duration) {
         mPositionUpdater.stopUpdating();
-        mView.setClipPosition(clipPosition);
+        mView.playbackStopped();
+        mView.setClipPosition(clipPosition, duration);
         if (mPlayer.isPlaying()) {
             mPlayer.pause();
         }
@@ -241,7 +268,7 @@
         public void onStartTrackingTouch(SeekBar arg0) {
             if (mPlayer.isPlaying()) {
                 mShouldResumePlaybackAfterSeeking = true;
-                stopPlaybackAtPosition(mPlayer.getCurrentPosition());
+                stopPlaybackAtPosition(mPlayer.getCurrentPosition(), mDuration.get());
             } else {
                 mShouldResumePlaybackAfterSeeking = false;
             }
@@ -250,7 +277,7 @@
         @Override
         public void onStopTrackingTouch(SeekBar arg0) {
             if (mPlayer.isPlaying()) {
-                stopPlaybackAtPosition(mPlayer.getCurrentPosition());
+                stopPlaybackAtPosition(mPlayer.getCurrentPosition(), mDuration.get());
             }
             if (mShouldResumePlaybackAfterSeeking) {
                 resetPrepareStartPlaying(mView.getDesiredClipPosition());
@@ -259,13 +286,13 @@
 
         @Override
         public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
-            mView.setClipPosition(seekBar.getProgress());
+            mView.setClipPosition(seekBar.getProgress(), seekBar.getMax());
         }
     }
 
-    private void changeRate(float rate) {
+    private void changeRate(float rate, int stringResourceId) {
         ((SingleThreadedMediaPlayerProxy) mPlayer).setVariableSpeed(rate);
-        mView.setRateDisplay(rate);
+        mView.setRateDisplay(rate, stringResourceId);
     }
 
     private class SpeakerphoneListener implements View.OnClickListener {
@@ -288,7 +315,7 @@
         @Override
         public void onClick(View arg0) {
             if (mPlayer.isPlaying()) {
-                stopPlaybackAtPosition(mPlayer.getCurrentPosition());
+                stopPlaybackAtPosition(mPlayer.getCurrentPosition(), mDuration.get());
             } else {
                 resetPrepareStartPlaying(mView.getDesiredClipPosition());
             }
@@ -304,6 +331,12 @@
         private final int mPeriodMillis;
         private final Object mLock = new Object();
         @GuardedBy("mLock") private ScheduledFuture<?> mScheduledFuture;
+        private final Runnable mSetClipPostitionRunnable = new Runnable() {
+            @Override
+            public void run() {
+                mView.setClipPosition(mPlayer.getCurrentPosition(), mDuration.get());
+            }
+        };
 
         public PositionUpdater(ScheduledExecutorService executorService, int periodMillis) {
             mExecutorService = executorService;
@@ -314,12 +347,7 @@
         public void run() {
             synchronized (mLock) {
                 if (mScheduledFuture != null) {
-                    mView.runOnUiThread(new Runnable() {
-                        @Override
-                        public void run() {
-                            mView.setClipPosition(mPlayer.getCurrentPosition());
-                        }
-                    });
+                    mView.runOnUiThread(mSetClipPostitionRunnable);
                 }
             }
         }
diff --git a/tests/src/com/android/contacts/CallDetailActivityTest.java b/tests/src/com/android/contacts/CallDetailActivityTest.java
index c279860..c1efa3f 100644
--- a/tests/src/com/android/contacts/CallDetailActivityTest.java
+++ b/tests/src/com/android/contacts/CallDetailActivityTest.java
@@ -29,13 +29,17 @@
 import android.net.Uri;
 import android.provider.CallLog;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
 import android.view.Menu;
+import android.widget.TextView;
 
+import java.util.List;
 import java.util.Locale;
 
 /**
  * Unit tests for the {@link CallDetailActivity}.
  */
+@LargeTest
 public class CallDetailActivityTest extends ActivityInstrumentationTestCase2<CallDetailActivity> {
     private static final String FAKE_VOICEMAIL_URI_STRING = "content://fake_uri";
     private Uri mUri;
@@ -112,6 +116,29 @@
         assertTrue(menu.findItem(R.id.remove_from_call_log).isVisible());
     }
 
+    /**
+     * Test to show that we are correctly displaying playback rate on the ui.
+     * <p>
+     * See bug http://b/5044075.
+     */
+    public void testVoicemailPlaybackRateDisplayedOnUi() throws Throwable {
+        setActivityIntentForTestVoicemailEntry();
+        CallDetailActivity activity = getActivity();
+        // Find the TextView containing the duration.  It should be initially displaying "00:00".
+        List<TextView> views = mTestUtils.getTextViewsWithString(activity, "00:00");
+        assertEquals(1, views.size());
+        TextView timeDisplay = views.get(0);
+        // Hit the plus button.  At this point we should be displaying "fast speed".
+        mTestUtils.clickButton(activity, R.id.rate_increase_button);
+        assertEquals("fast speed", mTestUtils.getText(timeDisplay));
+        // Hit the minus button.  We should be back to "normal" speed.
+        mTestUtils.clickButton(activity, R.id.rate_decrease_button);
+        assertEquals("normal speed", mTestUtils.getText(timeDisplay));
+        // Wait for one and a half seconds.  The timer will be back.
+        Thread.sleep(1500);
+        assertEquals("00:00", mTestUtils.getText(timeDisplay));
+    }
+
     private void setActivityIntentForTestCallEntry() {
         createTestCallEntry(false);
         setActivityIntent(new Intent(Intent.ACTION_VIEW, mUri));
diff --git a/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java b/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
index f02e7b0..3f4e49c 100644
--- a/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
+++ b/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
@@ -23,15 +23,10 @@
 
 import android.content.Context;
 import android.content.res.Resources;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
 import android.provider.CallLog.Calls;
 import android.test.AndroidTestCase;
+import android.view.LayoutInflater;
 import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
 
 import java.util.GregorianCalendar;
 import java.util.Locale;
@@ -50,14 +45,6 @@
     private static final String TEST_NUMBER = "14125555555";
     /** The formatted version of {@link #TEST_NUMBER}. */
     private static final String TEST_FORMATTED_NUMBER = "1-412-255-5555";
-    /** A drawable to be used for incoming calls. */
-    private static final Drawable TEST_INCOMING_DRAWABLE = new ColorDrawable(Color.BLACK);
-    /** A drawable to be used for outgoing calls. */
-    private static final Drawable TEST_OUTGOING_DRAWABLE = new ColorDrawable(Color.BLUE);
-    /** A drawable to be used for missed calls. */
-    private static final Drawable TEST_MISSED_DRAWABLE = new ColorDrawable(Color.RED);
-    /** A drawable to be used for voicemails. */
-    private static final Drawable TEST_VOICEMAIL_DRAWABLE = new ColorDrawable(Color.CYAN);
     /** The country ISO name used in the tests. */
     private static final String TEST_COUNTRY_ISO = "US";
 
@@ -72,14 +59,12 @@
         super.setUp();
         Context context = getContext();
         Resources resources = context.getResources();
-        CallTypeHelper callTypeHelper = new CallTypeHelper(resources, TEST_INCOMING_DRAWABLE,
-                TEST_OUTGOING_DRAWABLE, TEST_MISSED_DRAWABLE, TEST_VOICEMAIL_DRAWABLE);
+        LayoutInflater layoutInflater =
+                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        CallTypeHelper callTypeHelper = new CallTypeHelper(resources, layoutInflater);
         mPhoneNumberHelper = new PhoneNumberHelper(resources, TEST_VOICEMAIL_NUMBER);
-        mHelper = new PhoneCallDetailsHelper(
-                context, resources, callTypeHelper, mPhoneNumberHelper);
-        mViews = PhoneCallDetailsViews.createForTest(new TextView(context),
-                new LinearLayout(context), new TextView(context), new View(context),
-                new TextView(context), new TextView(context));
+        mHelper = new PhoneCallDetailsHelper(resources, callTypeHelper, mPhoneNumberHelper);
+        mViews = PhoneCallDetailsViews.createForTest(context);
     }
 
     @Override
@@ -143,16 +128,25 @@
 
     public void testSetPhoneCallDetails_CallTypeIcons() {
         setPhoneCallDetailsWithCallTypeIcons(Calls.INCOMING_TYPE);
-        assertCallTypeIconsEquals(TEST_INCOMING_DRAWABLE);
+        assertCallTypeIconsEquals(R.id.call_log_incoming_call_icon);
 
         setPhoneCallDetailsWithCallTypeIcons(Calls.OUTGOING_TYPE);
-        assertCallTypeIconsEquals(TEST_OUTGOING_DRAWABLE);
+        assertCallTypeIconsEquals(R.id.call_log_outgoing_call_icon);
 
         setPhoneCallDetailsWithCallTypeIcons(Calls.MISSED_TYPE);
-        assertCallTypeIconsEquals(TEST_MISSED_DRAWABLE);
+        assertCallTypeIconsEquals(R.id.call_log_missed_call_icon);
 
         setPhoneCallDetailsWithCallTypeIcons(Calls.VOICEMAIL_TYPE);
-        assertCallTypeIconsEquals(TEST_VOICEMAIL_DRAWABLE);
+        assertCallTypeIconsEquals(R.id.call_log_voicemail_icon);
+    }
+
+    public void testSetPhoneCallDetails_MultipleCallTypeIcons() {
+        setPhoneCallDetailsWithCallTypeIcons(Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE);
+        assertCallTypeIconsEquals(R.id.call_log_incoming_call_icon,
+                R.id.call_log_outgoing_call_icon);
+
+        setPhoneCallDetailsWithCallTypeIcons(Calls.MISSED_TYPE, Calls.MISSED_TYPE);
+        assertCallTypeIconsEquals(R.id.call_log_missed_call_icon, R.id.call_log_missed_call_icon);
     }
 
     public void testSetPhoneCallDetails_CallTypeText() {
@@ -187,6 +181,13 @@
         }
     }
 
+    public void testSetPhoneCallDetails_NameOnly() {
+        setPhoneCallDetailsNameOnly();
+        assertEquals(View.VISIBLE, mViews.nameView.getVisibility());
+        assertEquals(View.GONE, mViews.numberView.getVisibility());
+        assertEquals(View.GONE, mViews.callTypeView.getVisibility());
+    }
+
     /** Asserts that the name text field contains the value of the given string resource. */
     private void assertNameEqualsResource(int resId) {
         assertNameEquals(getContext().getString(resId));
@@ -208,12 +209,11 @@
     }
 
     /** Asserts that the call type contains the images with the given drawables. */
-    private void assertCallTypeIconsEquals(Drawable... drawables) {
-        assertEquals(drawables.length, mViews.callTypeIcons.getChildCount());
-        for (int index = 0; index < drawables.length; ++index) {
-            Drawable drawable = drawables[index];
-            ImageView imageView = (ImageView) mViews.callTypeIcons.getChildAt(index);
-            assertEquals(drawable, imageView.getDrawable());
+    private void assertCallTypeIconsEquals(int... ids) {
+        assertEquals(ids.length, mViews.callTypeIcons.getChildCount());
+        for (int index = 0; index < ids.length; ++index) {
+            int id = ids[index];
+            assertEquals(id, mViews.callTypeIcons.getChildAt(index).getId());
         }
         assertEquals(View.VISIBLE, mViews.callTypeIcons.getVisibility());
         assertEquals(View.GONE, mViews.callTypeText.getVisibility());
@@ -233,7 +233,7 @@
         mHelper.setPhoneCallDetails(mViews,
                 new PhoneCallDetails(number, formattedNumber, TEST_COUNTRY_ISO,
                         new int[]{ Calls.INCOMING_TYPE }, TEST_DATE, TEST_DURATION),
-                false, false);
+                false, false, false);
     }
 
     /** Sets the phone call details with default values and the given date. */
@@ -241,7 +241,7 @@
         mHelper.setPhoneCallDetails(mViews,
                 new PhoneCallDetails(TEST_NUMBER, TEST_FORMATTED_NUMBER, TEST_COUNTRY_ISO,
                         new int[]{ Calls.INCOMING_TYPE }, date, TEST_DURATION),
-                false, false);
+                false, false, false);
     }
 
     /** Sets the phone call details with default values and the given call types using icons. */
@@ -258,6 +258,13 @@
         mHelper.setPhoneCallDetails(mViews,
                 new PhoneCallDetails(TEST_NUMBER, TEST_FORMATTED_NUMBER, TEST_COUNTRY_ISO,
                         callTypes, TEST_DATE, TEST_DURATION),
-                useIcons, false);
+                useIcons, false, false);
+    }
+
+    private void setPhoneCallDetailsNameOnly() {
+        mHelper.setPhoneCallDetails(mViews,
+                new PhoneCallDetails(TEST_NUMBER, TEST_FORMATTED_NUMBER, TEST_COUNTRY_ISO,
+                        new int[]{ Calls.INCOMING_TYPE }, TEST_DATE, TEST_DURATION),
+                true, false, true);
     }
 }
diff --git a/tests/src/com/android/contacts/activities/CallLogActivityTests.java b/tests/src/com/android/contacts/activities/CallLogActivityTests.java
index 8372d9c..b642ffe 100644
--- a/tests/src/com/android/contacts/activities/CallLogActivityTests.java
+++ b/tests/src/com/android/contacts/activities/CallLogActivityTests.java
@@ -266,6 +266,31 @@
         assertNumberAndLabelAre(views, TEST_FORMATTED_NUMBER, numberLabel);
     }
 
+    @MediumTest
+    public void testBindView_WithQuickContactBadge() {
+        mCursor.moveToFirst();
+        insertWithCachedValues(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
+                "John Doe", Phone.TYPE_HOME, "");
+        View view = mAdapter.newStandAloneView(getActivity(), mParentView);
+        mAdapter.bindStandAloneView(view, getActivity(), mCursor);
+
+        CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+        assertEquals(View.VISIBLE, views.quickContactView.getVisibility());
+        assertEquals(View.GONE, views.plainPhotoView.getVisibility());
+    }
+
+    @MediumTest
+    public void testBindView_WithoutQuickContactBadge() {
+        mCursor.moveToFirst();
+        insert(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE);
+        View view = mAdapter.newStandAloneView(getActivity(), mParentView);
+        mAdapter.bindStandAloneView(view, getActivity(), mCursor);
+
+        CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+        assertEquals(View.GONE, views.quickContactView.getVisibility());
+        assertEquals(View.VISIBLE, views.plainPhotoView.getVisibility());
+    }
+
     /** Returns the label associated with a given phone type. */
     private CharSequence getTypeLabel(int phoneType) {
         return Phone.getTypeLabel(getActivity().getResources(), phoneType, "");
diff --git a/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java b/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java
index 626d7c6..79ebf4d 100644
--- a/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java
+++ b/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java
@@ -18,19 +18,14 @@
 
 import com.android.contacts.PhoneCallDetails;
 import com.android.contacts.PhoneCallDetailsHelper;
-import com.android.contacts.PhoneCallDetailsViews;
-import com.android.contacts.R;
 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.LayoutInflater;
 import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.QuickContactBadge;
-import android.widget.TextView;
 
 /**
  * Unit tests for {@link CallLogListItemHelper}.
@@ -61,21 +56,14 @@
         super.setUp();
         Context context = getContext();
         Resources resources = context.getResources();
-        CallTypeHelper callTypeHelper = new CallTypeHelper(resources,
-                resources.getDrawable(R.drawable.ic_call_incoming_holo_dark),
-                resources.getDrawable(R.drawable.ic_call_outgoing_holo_dark),
-                resources.getDrawable(R.drawable.ic_call_missed_holo_dark),
-                resources.getDrawable(R.drawable.ic_call_voicemail_holo_dark));
+        LayoutInflater layoutInflater =
+                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        CallTypeHelper callTypeHelper = new CallTypeHelper(resources, layoutInflater);
         mPhoneNumberHelper = new PhoneNumberHelper(resources, TEST_VOICEMAIL_NUMBER);
-        PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper(context,
+        PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper(
                 resources, callTypeHelper, mPhoneNumberHelper);
         mHelper = new CallLogListItemHelper(phoneCallDetailsHelper, mPhoneNumberHelper);
-        mViews = CallLogListItemViews.createForTest(new QuickContactBadge(context),
-                new ImageView(context), new ImageView(context), new View(context),
-                PhoneCallDetailsViews.createForTest(new TextView(context),
-                        new LinearLayout(context), new TextView(context), new TextView(context),
-                        new TextView(context), new TextView(context)),
-                new View(context), new View(context), new TextView(context));
+        mViews = CallLogListItemViews.createForTest(context);
     }
 
     @Override
@@ -89,6 +77,7 @@
         setPhoneCallDetailsWithNumber("12125551234", "1-212-555-1234");
         assertEquals(View.VISIBLE, mViews.callView.getVisibility());
         assertEquals(View.GONE, mViews.playView.getVisibility());
+        assertEquals(View.GONE, mViews.unheardView.getVisibility());
     }
 
     public void testSetPhoneCallDetails_Unknown() {
@@ -110,34 +99,39 @@
         setPhoneCallDetailsWithNumber(TEST_VOICEMAIL_NUMBER, TEST_VOICEMAIL_NUMBER);
         assertEquals(View.VISIBLE, mViews.callView.getVisibility());
         assertEquals(View.GONE, mViews.playView.getVisibility());
+        assertEquals(View.GONE, mViews.unheardView.getVisibility());
     }
 
-    public void testSetPhoneCallDetails_Voicemail() {
+    public void testSetPhoneCallDetails_ReadVoicemail() {
         setPhoneCallDetailsWithTypes(Calls.VOICEMAIL_TYPE);
-        assertEquals(View.VISIBLE, mViews.callView.getVisibility());
+        assertEquals(View.GONE, mViews.callView.getVisibility());
         assertEquals(View.VISIBLE, mViews.playView.getVisibility());
+        assertEquals(View.GONE, mViews.unheardView.getVisibility());
+    }
+
+    public void testSetPhoneCallDetails_UnreadVoicemail() {
+        setUnreadPhoneCallDetailsWithTypes(Calls.VOICEMAIL_TYPE);
+        assertEquals(View.GONE, mViews.callView.getVisibility());
+        assertEquals(View.VISIBLE, mViews.playView.getVisibility());
+        assertEquals(View.VISIBLE, mViews.unheardView.getVisibility());
     }
 
     public void testSetPhoneCallDetails_VoicemailFromUnknown() {
         setPhoneCallDetailsWithNumberAndType(CallerInfo.UNKNOWN_NUMBER, CallerInfo.UNKNOWN_NUMBER,
                 Calls.VOICEMAIL_TYPE);
+        assertEquals(View.GONE, mViews.callView.getVisibility());
         assertEquals(View.VISIBLE, mViews.playView.getVisibility());
-        assertEmptyCallButton();
+        assertEquals(View.GONE, mViews.unheardView.getVisibility());
     }
 
     /** Asserts that the whole call area is gone. */
     private void assertNoCallButton() {
         assertEquals(View.GONE, mViews.callView.getVisibility());
         assertEquals(View.GONE, mViews.playView.getVisibility());
+        assertEquals(View.GONE, mViews.unheardView.getVisibility());
         assertEquals(View.GONE, mViews.dividerView.getVisibility());
     }
 
-    /** Asserts that the call area is present but empty. */
-    private void assertEmptyCallButton() {
-        assertEquals(View.INVISIBLE, mViews.callView.getVisibility());
-        assertEquals(View.VISIBLE, mViews.dividerView.getVisibility());
-    }
-
     /** Sets the details of a phone call using the specified phone number. */
     private void setPhoneCallDetailsWithNumber(String number, String formattedNumber) {
         setPhoneCallDetailsWithNumberAndType(number, formattedNumber, Calls.INCOMING_TYPE);
@@ -159,4 +153,12 @@
                         types, TEST_DATE, TEST_DURATION),
                 true, false);
     }
+
+    /** Sets the details of a phone call using the specified call type. */
+    private void setUnreadPhoneCallDetailsWithTypes(int... types) {
+        mHelper.setPhoneCallDetails(mViews,
+                new PhoneCallDetails(TEST_NUMBER, TEST_FORMATTED_NUMBER, TEST_COUNTRY_ISO,
+                        types, TEST_DATE, TEST_DURATION),
+                true, true);
+    }
 }
diff --git a/tests/src/com/android/contacts/model/AccountTypeTest.java b/tests/src/com/android/contacts/model/AccountTypeTest.java
index 4898cf3..de66694 100644
--- a/tests/src/com/android/contacts/model/AccountTypeTest.java
+++ b/tests/src/com/android/contacts/model/AccountTypeTest.java
@@ -17,9 +17,14 @@
 package com.android.contacts.model;
 
 import com.android.contacts.tests.R;
+import com.google.common.collect.Lists;
 
 import android.content.Context;
 import android.test.AndroidTestCase;
+import android.test.MoreAsserts;
+
+import java.util.ArrayList;
+import java.util.Collections;
 
 /**
  * Test case for {@link AccountType}.
@@ -87,4 +92,53 @@
         assertEquals(getTestContext().getString(externalResID),
                 accountType.getInviteContactActionLabel(c));
     }
+
+    public void testDisplayLabelComparator() {
+        final AccountTypeForDisplayLabelTest EMPTY = new AccountTypeForDisplayLabelTest("");
+        final AccountTypeForDisplayLabelTest NULL = new AccountTypeForDisplayLabelTest(null);
+        final AccountTypeForDisplayLabelTest AA = new AccountTypeForDisplayLabelTest("aa");
+        final AccountTypeForDisplayLabelTest BBB = new AccountTypeForDisplayLabelTest("bbb");
+        final AccountTypeForDisplayLabelTest C = new AccountTypeForDisplayLabelTest("c");
+
+        assertTrue(compareDisplayLabel(AA, BBB) < 0);
+        assertTrue(compareDisplayLabel(BBB, C) < 0);
+        assertTrue(compareDisplayLabel(AA, C) < 0);
+        assertTrue(compareDisplayLabel(AA, AA) == 0);
+        assertTrue(compareDisplayLabel(BBB, AA) > 0);
+
+        assertTrue(compareDisplayLabel(EMPTY, AA) < 0);
+        assertTrue(compareDisplayLabel(EMPTY, NULL) == 0);
+    }
+
+    private int compareDisplayLabel(AccountType lhs, AccountType rhs) {
+        return new AccountType.DisplayLabelComparator(getContext()).compare(lhs, rhs);
+    }
+
+    private class AccountTypeForDisplayLabelTest extends AccountType {
+        private final String mDisplayLabel;
+
+        public AccountTypeForDisplayLabelTest(String displayLabel) {
+            mDisplayLabel = displayLabel;
+        }
+
+        @Override
+        public CharSequence getDisplayLabel(Context context) {
+            return mDisplayLabel;
+        }
+
+        @Override
+        public int getHeaderColor(Context context) {
+            return 0;
+        }
+
+        @Override
+        public int getSideBarColor(Context context) {
+            return 0;
+        }
+
+        @Override
+        public boolean isGroupMembershipEditable() {
+            return false;
+        }
+    }
 }
diff --git a/tests/src/com/android/contacts/util/IntegrationTestUtils.java b/tests/src/com/android/contacts/util/IntegrationTestUtils.java
index a61ea57..afea349 100644
--- a/tests/src/com/android/contacts/util/IntegrationTestUtils.java
+++ b/tests/src/com/android/contacts/util/IntegrationTestUtils.java
@@ -72,6 +72,16 @@
         });
     }
 
+    /** Returns the result of running {@link TextView#getText()} on the ui thread. */
+    public CharSequence getText(final TextView view) throws Throwable {
+        return runOnUiThreadAndGetTheResult(new Callable<CharSequence>() {
+            @Override
+            public CharSequence call() {
+                return view.getText();
+            }
+        });
+    }
+
     // TODO: Move this class and the appropriate documentation into a test library, having checked
     // first to see if exactly this code already exists or not.
     /**