Merge "Fix classcast exception bug after sending email."
diff --git a/res/drawable-hdpi/btn_star_off_normal_holo_dark.png b/res/drawable-hdpi/btn_star_off_normal_holo_dark.png
new file mode 100644
index 0000000..1ab75f9
--- /dev/null
+++ b/res/drawable-hdpi/btn_star_off_normal_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/btn_star_on_normal_holo_dark.png b/res/drawable-hdpi/btn_star_on_normal_holo_dark.png
new file mode 100644
index 0000000..8cd764a
--- /dev/null
+++ b/res/drawable-hdpi/btn_star_on_normal_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/statusbox_attribute_holo.9.png b/res/drawable-hdpi/statusbox_attribute_holo.9.png
deleted file mode 100644
index 13ffd7a..0000000
--- a/res/drawable-hdpi/statusbox_attribute_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/btn_star_off_normal_holo_dark.png b/res/drawable-mdpi/btn_star_off_normal_holo_dark.png
new file mode 100644
index 0000000..069e1ca
--- /dev/null
+++ b/res/drawable-mdpi/btn_star_off_normal_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/btn_star_on_normal_holo_dark.png b/res/drawable-mdpi/btn_star_on_normal_holo_dark.png
new file mode 100644
index 0000000..d98dc94
--- /dev/null
+++ b/res/drawable-mdpi/btn_star_on_normal_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/statusbox_attribute_holo.9.png b/res/drawable-mdpi/statusbox_attribute_holo.9.png
deleted file mode 100644
index bc5e10f..0000000
--- a/res/drawable-mdpi/statusbox_attribute_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/btn_star_off_normal_holo_dark.png b/res/drawable-xhdpi/btn_star_off_normal_holo_dark.png
new file mode 100644
index 0000000..3774545
--- /dev/null
+++ b/res/drawable-xhdpi/btn_star_off_normal_holo_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/btn_star_on_normal_holo_dark.png b/res/drawable-xhdpi/btn_star_on_normal_holo_dark.png
new file mode 100644
index 0000000..11c557c
--- /dev/null
+++ b/res/drawable-xhdpi/btn_star_on_normal_holo_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/statusbox_attribute_holo.9.png b/res/drawable-xhdpi/statusbox_attribute_holo.9.png
deleted file mode 100644
index b2b82e4..0000000
--- a/res/drawable-xhdpi/statusbox_attribute_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/btn_star_holo_dark.xml b/res/drawable/btn_star_holo_dark.xml
new file mode 100644
index 0000000..2949de9
--- /dev/null
+++ b/res/drawable/btn_star_holo_dark.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true" android:drawable="@drawable/btn_star_on_normal_holo_dark"/>
+    <item android:drawable="@drawable/btn_star_off_normal_holo_dark"/>
+</selector>
\ No newline at end of file
diff --git a/res/layout-sw580dp-w1000dp/contact_detail_updates_fragment.xml b/res/layout-sw580dp-w1000dp/contact_detail_updates_fragment.xml
index 427f369..0e89d24 100644
--- a/res/layout-sw580dp-w1000dp/contact_detail_updates_fragment.xml
+++ b/res/layout-sw580dp-w1000dp/contact_detail_updates_fragment.xml
@@ -14,22 +14,9 @@
      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_updates_fragment"
+<ListView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/list"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical"
-    android:padding="16dip">
-
-    <include
-        android:id="@+id/title"
-        layout="@layout/contact_detail_kind_title_entry_view" />
-
-    <ListView android:id="@android:id/list"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:background="@color/background_social_updates"
-        android:divider="@null"/>
-
-</LinearLayout>
+    android:background="@color/background_social_updates"
+    android:divider="@null"/>
diff --git a/res/layout-sw580dp/contact_picker_content.xml b/res/layout-sw580dp/contact_picker_content.xml
deleted file mode 100644
index 225b725..0000000
--- a/res/layout-sw580dp/contact_picker_content.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
-
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="2dip"
-        android:layout_marginTop="1dip"
-        android:layout_marginBottom="1dip"
-        android:background="#7e7e87" />
-
-    <view
-        class="com.android.contacts.list.ContactEntryListView"
-        android:id="@android:id/list"
-        android:layout_width="match_parent"
-        android:layout_height="0dip"
-        android:fastScrollEnabled="true"
-        android:layout_weight="1"/>
-
-    <ViewStub
-        android:id="@+id/footer_stub"
-        android:layout="@layout/footer_panel"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content" />
-</LinearLayout>
diff --git a/res/layout-w470dp/contact_detail_fragment.xml b/res/layout-w470dp/contact_detail_fragment.xml
index d63236d..982abbb 100644
--- a/res/layout-w470dp/contact_detail_fragment.xml
+++ b/res/layout-w470dp/contact_detail_fragment.xml
@@ -76,7 +76,6 @@
         android:layout_height="match_parent"
         android:layout_alignParentLeft="true"
         android:layout_alignParentTop="true"
-        android:background="@android:color/black"
         android:visibility="gone"/>
 
     <View
diff --git a/res/layout-w470dp/contact_detail_updates_fragment.xml b/res/layout-w470dp/contact_detail_updates_fragment.xml
index dd7cfbd..ccb7123 100644
--- a/res/layout-w470dp/contact_detail_updates_fragment.xml
+++ b/res/layout-w470dp/contact_detail_updates_fragment.xml
@@ -20,22 +20,11 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <LinearLayout
+    <ListView android:id="@android:id/list"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="vertical">
-
-        <include
-            android:id="@+id/title"
-            layout="@layout/contact_detail_kind_title_entry_view" />
-
-        <ListView android:id="@android:id/list"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:background="@color/background_social_updates"
-            android:divider="@null"/>
-
-    </LinearLayout>
+        android:layout_height="wrap_content"
+        android:background="@color/background_social_updates"
+        android:divider="@null"/>
 
     <View
         android:id="@+id/alpha_overlay"
@@ -43,7 +32,6 @@
         android:layout_height="match_parent"
         android:layout_alignParentLeft="true"
         android:layout_alignParentTop="true"
-        android:background="@android:color/black"
         android:visibility="gone"/>
 
     <View
diff --git a/res/layout/call_detail.xml b/res/layout/call_detail.xml
index 714bbd8..157c761 100644
--- a/res/layout/call_detail.xml
+++ b/res/layout/call_detail.xml
@@ -83,6 +83,7 @@
             android:id="@+id/voicemail_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:paddingBottom="@dimen/call_log_icon_margin"
             android:layout_below="@id/blue_separator"
             android:background="@android:color/black"
         >
@@ -118,7 +119,7 @@
             android:layout_marginLeft="@dimen/call_detail_contact_name_margin"
             android:gravity="center_vertical"
             android:textColor="?attr/call_log_primary_text_color"
-            android:textSize="18sp"
+            android:textAppearance="?android:attr/textAppearanceMedium"
             android:singleLine="true"
         />
         <ImageButton
@@ -134,6 +135,7 @@
         <FrameLayout android:id="@+id/call_and_sms_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:layout_marginBottom="@dimen/call_log_icon_margin"
             android:layout_below="@id/voicemail_container"
             android:background="@android:color/black"
         >
@@ -142,7 +144,6 @@
                 android:layout_width="match_parent"
                 android:layout_height="@dimen/call_log_list_item_height"
                 android:orientation="horizontal"
-                android:layout_marginTop="@dimen/call_log_icon_margin"
                 android:gravity="center_vertical"
                 android:background="@drawable/dialpad_background"
             >
@@ -158,31 +159,18 @@
                     android:background="@drawable/btn_dial"
                 >
 
-                    <TextView android:id="@+id/call_and_sms_text1"
+                    <TextView android:id="@+id/call_and_sms_text"
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
-                        android:textAppearance="?android:attr/textAppearanceLarge"
+                        android:textAppearance="?android:attr/textAppearanceMedium"
                     />
 
-                    <LinearLayout android:id="@+id/call_and_sms_line2"
+                    <TextView android:id="@+id/call_and_sms_label"
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
-                        android:orientation="horizontal"
-                    >
-                        <TextView android:id="@+id/call_and_sms_label"
-                            android:layout_width="wrap_content"
-                            android:layout_height="wrap_content"
-                            android:layout_marginRight="5dip"
-                            android:textAppearance="?android:attr/textAppearanceSmall"
-                            android:textStyle="bold"
-                        />
-
-                        <TextView android:id="@+id/call_and_sms_number"
-                            android:layout_width="wrap_content"
-                            android:layout_height="wrap_content"
-                            android:textAppearance="?android:attr/textAppearanceSmall"
-                        />
-                    </LinearLayout>
+                        android:textAppearance="?android:attr/textAppearanceSmall"
+                        android:textAllCaps="true"
+                    />
 
                 </LinearLayout>
 
diff --git a/res/layout/call_detail_history_item.xml b/res/layout/call_detail_history_item.xml
index 674b034..fa5bc28 100644
--- a/res/layout/call_detail_history_item.xml
+++ b/res/layout/call_detail_history_item.xml
@@ -41,6 +41,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginLeft="@dimen/call_log_icon_margin"
+            android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="@color/secondary_text_color"
         />
     </LinearLayout>
@@ -48,12 +49,14 @@
         android:id="@+id/date"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceSmall"
         android:textColor="@color/secondary_text_color"
     />
     <TextView
         android:id="@+id/duration"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceSmall"
         android:textColor="@color/secondary_text_color"
     />
 </LinearLayout>
diff --git a/res/layout/call_log_list_item.xml b/res/layout/call_log_list_item.xml
index 8bd6a19..734e1b8 100644
--- a/res/layout/call_log_list_item.xml
+++ b/res/layout/call_log_list_item.xml
@@ -141,17 +141,33 @@
         </LinearLayout>
     </RelativeLayout>
 
-    <TextView
-        android:id="@+id/call_log_header_text"
+    <LinearLayout
+        android:id="@+id/call_log_header"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="@dimen/call_log_inner_margin"
-        android:layout_marginRight="@dimen/call_log_inner_margin"
-        android:textSize="14sp"
-        android:textStyle="bold"
-        android:textColor="?attr/call_log_header_color"
-        android:padding="@dimen/call_log_inner_margin"
-        android:focusable="true"
-        android:drawableBottom="@android:color/holo_blue_light"
-    />
+        android:paddingLeft="@dimen/call_log_outer_margin"
+        android:paddingRight="@dimen/call_log_outer_margin"
+        android:paddingTop="@dimen/call_log_inner_margin"
+        android:paddingBottom="@dimen/call_log_inner_margin"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@+id/call_log_header_text"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingLeft="@dimen/call_log_inner_margin"
+            android:paddingRight="@dimen/call_log_inner_margin"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textStyle="bold"
+            android:textColor="?attr/call_log_header_color"
+            android:textAllCaps="true"
+            android:focusable="true"
+        />
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="2dip"
+            android:background="@color/call_log_voicemail_highlight_color"/>
+    </LinearLayout>
 </view>
diff --git a/res/layout/carousel_about_tab.xml b/res/layout/carousel_about_tab.xml
index ad763be..c7c4394 100644
--- a/res/layout/carousel_about_tab.xml
+++ b/res/layout/carousel_about_tab.xml
@@ -19,8 +19,7 @@
     class="com.android.contacts.detail.CarouselTab"
     android:layout_width="0dip"
     android:layout_height="match_parent"
-    android:layout_weight="1"
-    android:background="@color/detail_tab_background">
+    android:layout_weight="1">
 
     <ImageView android:id="@+id/photo"
         android:scaleType="centerCrop"
@@ -45,8 +44,6 @@
         android:layout_alignParentLeft="true"
         android:layout_alignParentTop="true"
         android:layout_marginBottom="@dimen/detail_tab_carousel_tab_label_height"
-        android:background="@android:color/black"
-        android:alpha="0"
         android:visibility="gone"/>
 
     <TextView
diff --git a/res/layout/carousel_updates_tab.xml b/res/layout/carousel_updates_tab.xml
index b41829f..9637023 100644
--- a/res/layout/carousel_updates_tab.xml
+++ b/res/layout/carousel_updates_tab.xml
@@ -33,7 +33,6 @@
         android:layout_alignParentLeft="true"
         android:visibility="gone" />
 
-
     <!-- Transparent view to overlay on the update photo
     (to allow white text to appear over a white photo). -->
     <View
@@ -65,8 +64,6 @@
         android:layout_alignParentLeft="true"
         android:layout_alignParentTop="true"
         android:layout_marginBottom="@dimen/detail_tab_carousel_tab_label_height"
-        android:background="@android:color/black"
-        android:alpha="0"
         android:visibility="gone"/>
 
     <TextView
diff --git a/res/layout/contact_detail_list_item.xml b/res/layout/contact_detail_list_item.xml
index ccfa01d..e292f39 100644
--- a/res/layout/contact_detail_list_item.xml
+++ b/res/layout/contact_detail_list_item.xml
@@ -24,8 +24,8 @@
     android:layout_height="wrap_content"
     android:orientation="horizontal"
     android:gravity="center_vertical"
-    android:paddingTop="12dip"
-    android:paddingBottom="12dip"
+    android:paddingTop="8dip"
+    android:paddingBottom="8dip"
     android:minHeight="@dimen/detail_min_line_item_height">
 
     <!-- Note: padding might be controlled programatically -->
diff --git a/res/layout/contact_detail_list_padding.xml b/res/layout/contact_detail_list_padding.xml
new file mode 100644
index 0000000..8095731
--- /dev/null
+++ b/res/layout/contact_detail_list_padding.xml
@@ -0,0 +1,28 @@
+<?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.
+-->
+
+<!-- The actual padding is embedded in a FrameLayout since we cannot change the
+     visibility of a header view in a ListView without having a parent view. -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+    <View
+        android:id="@+id/contact_detail_list_padding"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/contact_browser_list_top_margin" />
+</FrameLayout>
+
diff --git a/res/layout/contact_detail_updates_fragment.xml b/res/layout/contact_detail_updates_fragment.xml
index 2393ace..a949cd8 100644
--- a/res/layout/contact_detail_updates_fragment.xml
+++ b/res/layout/contact_detail_updates_fragment.xml
@@ -14,17 +14,11 @@
      limitations under the License.
 -->
 
-<FrameLayout
+<ListView
     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_updates_fragment"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <ListView android:id="@android:id/list"
+    android:id="@android:id/list"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:background="@color/background_social_updates"
         android:divider="@null"/>
-
-</FrameLayout>
diff --git a/res/layout/contact_picker.xml b/res/layout/contact_picker.xml
index c3fe2fa..96bf334 100644
--- a/res/layout/contact_picker.xml
+++ b/res/layout/contact_picker.xml
@@ -18,8 +18,6 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     class="com.android.contacts.widget.FullHeightLinearLayout"
     style="@style/ContactPickerLayout"
-    android:paddingLeft="8dip"
-    android:paddingRight="8dip"
     android:orientation="vertical"
     android:layout_height="match_parent">
     <view
@@ -27,18 +25,18 @@
         android:id="@+id/search_view"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="10dip"
-        android:layout_marginRight="10dip"
-        android:layout_marginBottom="10dip"
+        android:layout_marginLeft="0dip"
+        android:layout_marginRight="32dip"
         android:iconifiedByDefault="false" />
+    <!-- will contain an appropriate contacts list -->
     <FrameLayout
+        android:id="@+id/list_container"
         android:layout_width="match_parent"
         android:layout_height="0dip"
-        android:layout_weight="1"
-        android:id="@+id/list_container">
-    </FrameLayout>
+        android:layout_weight="1" />
 
     <View
+        android:id="@+id/divider"
         android:layout_width="match_parent"
         android:layout_height="1dip"
         android:layout_marginLeft="16dip"
@@ -48,7 +46,9 @@
     <LinearLayout
         style="?android:attr/buttonBarStyle"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content">
+        android:layout_height="wrap_content"
+        android:paddingLeft="16dip"
+        android:paddingRight="16dip">
         <Button
             style="?android:attr/buttonBarButtonStyle"
             android:id="@+id/cancel"
diff --git a/res/layout/contact_picker_content.xml b/res/layout/contact_picker_content.xml
index 6792f9c..c30add7 100644
--- a/res/layout/contact_picker_content.xml
+++ b/res/layout/contact_picker_content.xml
@@ -26,6 +26,8 @@
         android:id="@android:id/list"
         android:layout_width="match_parent"
         android:layout_height="0dip"
+        android:layout_marginLeft="?attr/contact_browser_list_padding_left"
+        android:layout_marginRight="?attr/contact_browser_list_padding_right"
         android:fastScrollEnabled="true"
         android:layout_weight="1" />
 
diff --git a/res/layout/contacts_list_content.xml b/res/layout/contacts_list_content.xml
index f98d751..66c3936 100644
--- a/res/layout/contacts_list_content.xml
+++ b/res/layout/contacts_list_content.xml
@@ -22,17 +22,19 @@
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/pinned_header_list_layout"
-    android:paddingTop="@dimen/contact_browser_list_top_margin"
     android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent" >
 
-    <!-- Shown only when an Account filter is set. -->
+    <!-- Shown only when an Account filter is set.
+         - paddingTop should be here to show "shade" effect correctly. -->
     <LinearLayout
         android:id="@+id/account_filter_header_container"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:minHeight="?attr/list_item_header_height"
         android:orientation="vertical"
+        android:paddingTop="@dimen/contact_browser_list_top_margin"
         android:layout_marginLeft="@dimen/contact_browser_list_header_left_margin"
         android:layout_marginRight="@dimen/contact_browser_list_header_right_margin"
         android:visibility="gone">
@@ -40,11 +42,9 @@
             android:id="@+id/account_filter_header"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:minHeight="@dimen/contact_filter_header_min_height"
             android:singleLine="true"
             android:ellipsize="end"
             android:textStyle="bold"
-            android:gravity="left|center_vertical"
             android:textAllCaps="true"
             android:paddingLeft="@dimen/contact_browser_list_item_text_indent"
             android:textAppearance="?android:attr/textAppearanceSmall"
@@ -59,9 +59,9 @@
         class="com.android.contacts.list.ContactEntryListView"
         android:id="@android:id/list"
         android:layout_width="match_parent"
-           android:layout_height="0dip"
-           android:layout_marginLeft="@dimen/contact_browser_list_left_margin"
-        android:layout_marginRight="@dimen/contact_browser_list_right_margin"
+        android:layout_height="0dip"
+        android:layout_marginLeft="?attr/contact_browser_list_padding_left"
+        android:layout_marginRight="?attr/contact_browser_list_padding_right"
         android:fastScrollEnabled="true"
         android:layout_weight="1" />
 
diff --git a/res/layout/directory_header.xml b/res/layout/directory_header.xml
index af0b5bd..6043c7b 100644
--- a/res/layout/directory_header.xml
+++ b/res/layout/directory_header.xml
@@ -19,12 +19,14 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     style="@style/DirectoryHeader"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content">
+    android:layout_height="wrap_content"
+    android:minHeight="?attr/list_item_header_height"
+    android:paddingLeft="?attr/list_item_padding_left"
+    android:paddingRight="?attr/list_item_padding_right">
     <TextView
         android:id="@+id/display_name"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:minHeight="@dimen/directory_header_height"
         android:layout_toRightOf="@+id/label"
         android:layout_toLeftOf="@+id/count"
         android:layout_centerVertical="true"
@@ -32,7 +34,9 @@
         android:layout_marginRight="8dip"
         android:textAppearance="?android:attr/textAppearanceSmall"
         android:textColor="?android:attr/textColorSecondary"
-        android:singleLine="true" />
+        android:singleLine="true"
+        android:textStyle="bold"
+        android:textAllCaps="true" />
     <TextView
         android:id="@+id/label"
         android:layout_width="wrap_content"
@@ -41,16 +45,19 @@
         android:layout_alignBaseline="@id/display_name"
         android:layout_marginLeft="8dip"
         android:textAppearance="?android:attr/textAppearanceSmall"
-        android:textColor="?android:attr/textColorSecondary" />
+        android:textColor="?android:attr/textColorSecondary"
+        android:singleLine="true"
+        android:textStyle="bold"
+        android:textAllCaps="true" />
     <TextView
         android:id="@+id/count"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentRight="true"
-        android:layout_marginRight="8dip"
         android:layout_alignBaseline="@id/display_name"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-        android:textColor="?android:attr/textColorSecondary" />
+        android:singleLine="true"
+        android:textSize="12sp"
+        android:textColor="@color/contact_count_text_color" />
     <View
         android:id="@+id/contact_filter_header_bottom_divider"
         style="@style/SectionDivider"
diff --git a/res/layout/favorites_star.xml b/res/layout/favorites_star.xml
index 4b859b4..5bdc091 100644
--- a/res/layout/favorites_star.xml
+++ b/res/layout/favorites_star.xml
@@ -29,6 +29,5 @@
         android:layout_gravity="center_vertical"
         android:contentDescription="@string/description_star"
         android:visibility="invisible"
-        style="?android:attr/starStyle"/>
-
+        android:button="@drawable/btn_star_holo_dark"/>
 </FrameLayout>
\ No newline at end of file
diff --git a/res/layout/group_browse_list_account_header.xml b/res/layout/group_browse_list_account_header.xml
index f739ea2..b1d873d 100644
--- a/res/layout/group_browse_list_account_header.xml
+++ b/res/layout/group_browse_list_account_header.xml
@@ -18,54 +18,43 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:background="@drawable/list_background_holo"
-    android:paddingLeft="@dimen/group_list_header_padding"
-    android:paddingRight="@dimen/group_list_header_padding"
-    android:paddingTop="@dimen/group_list_header_padding"
+    android:minHeight="?attr/list_item_header_height"
     android:orientation="vertical">
 
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:paddingLeft="?attr/list_item_header_text_indent"
         android:orientation="horizontal">
 
         <TextView
             android:id="@+id/account_type"
-            android:layout_width="wrap_content"
+            android:layout_width="0px"
             android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:layout_weight="1"
+            android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="@color/people_app_theme_color"
             android:textStyle="bold"
             android:textAllCaps="true"
             android:singleLine="true"/>
 
+        <!-- TODO: Shold use correct color with a correct name (content should be same).
+             can use "?android:attr/textColorTertiary" -->
         <TextView
             android:id="@+id/account_name"
-            android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:layout_marginLeft="@dimen/group_list_header_padding"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:singleLine="true"
-            android:ellipsize="middle"
-            android:textColor="@color/people_app_theme_color"/>
-
-        <TextView
-            android:id="@+id/group_count"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:gravity="right"
-            android:singleLine="true"
-            android:layout_marginLeft="@dimen/group_list_header_padding"
+            android:layout_gravity="center_vertical"
             android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorTertiary"/>
-
+            android:textColor="@color/contact_count_text_color"
+            android:textSize="12sp"
+            android:singleLine="true"
+            android:ellipsize="middle" />
     </LinearLayout>
 
     <View
         android:layout_width="match_parent"
         android:layout_height="1dip"
-        android:layout_marginTop="@dimen/group_list_header_padding"
-        android:background="@color/people_app_theme_color"/>
+        android:background="@color/people_app_theme_color" />
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/res/layout/group_browse_list_fragment.xml b/res/layout/group_browse_list_fragment.xml
index 9e6bd27..6e82e8f 100644
--- a/res/layout/group_browse_list_fragment.xml
+++ b/res/layout/group_browse_list_fragment.xml
@@ -25,20 +25,23 @@
       class="com.android.contacts.widget.AutoScrollListView"
       android:layout_width="match_parent"
       android:layout_height="0dip"
-      android:fastScrollEnabled="true"
+      android:paddingTop="@dimen/contact_browser_list_top_margin"
+      android:paddingLeft="16dip"
+      android:paddingRight="16dip"
       android:scrollbarStyle="outsideOverlay"
       android:layout_weight="1"
       android:cacheColorHint="@android:color/transparent"
       android:divider="@null" />
 
     <TextView
-      android:id="@+id/empty"
-      android:layout_marginTop="@dimen/empty_message_top_margin"
-      android:layout_width="match_parent"
-      android:layout_height="wrap_content"
-      android:gravity="center_horizontal"
-      android:textAppearance="?android:attr/textAppearanceMedium"
-      android:text="@string/noGroups" />
+        android:id="@+id/empty"
+        android:layout_marginTop="@dimen/empty_message_top_margin"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="8dip"
+        android:gravity="center_horizontal"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:text="@string/noGroups" />
 
     <LinearLayout
       android:id="@+id/add_accounts"
diff --git a/res/layout/group_browse_list_item.xml b/res/layout/group_browse_list_item.xml
index 326b413..599cc13 100644
--- a/res/layout/group_browse_list_item.xml
+++ b/res/layout/group_browse_list_item.xml
@@ -19,35 +19,33 @@
     android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:minHeight="@dimen/detail_min_line_item_height">
+    android:paddingLeft="?attr/list_item_padding_left"
+    android:paddingTop="?attr/list_item_padding_top"
+    android:paddingRight="?attr/list_item_padding_right"
+    android:paddingBottom="?attr/list_item_padding_bottom"
+    android:minHeight="@dimen/detail_min_line_item_height" >
 
-    <ImageView
+    <View
         android:id="@+id/divider"
         android:layout_width="match_parent"
         android:layout_height="1dip"
-        android:paddingLeft="10dip"
-        android:paddingRight="10dip"
-        android:scaleType="fitXY"
-        android:src="@color/people_app_theme_color"/>
+        android:background="?android:attr/listDivider" />
 
     <include
         android:id="@+id/group_list_header"
         layout="@layout/group_browse_list_account_header"
-        android:paddingRight="20dip"
-        android:paddingBottom="10dip"
         android:visibility="gone" />
 
     <RelativeLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:paddingTop="10dip"
-        android:paddingRight="20dip"
-        android:paddingBottom="10dip"
-        style="@style/GroupBrowseListItem">
+        android:paddingTop="8dip"
+        android:paddingBottom="8dip">
 
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:paddingLeft="?attr/list_item_text_indent"
             android:orientation="vertical"
             android:layout_toLeftOf="@+id/icons"
             android:layout_alignParentLeft="true"
@@ -57,8 +55,6 @@
                 android:id="@+id/label"
                 android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
-                android:paddingLeft="10dip"
-                android:paddingRight="10dip"
                 android:textAppearance="?android:attr/textAppearanceMedium"
                 android:ellipsize="end"
                 android:singleLine="true" />
@@ -67,8 +63,6 @@
                 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"
diff --git a/res/layout/join_contact_picker.xml b/res/layout/join_contact_picker.xml
index 20a7740..ffea137 100644
--- a/res/layout/join_contact_picker.xml
+++ b/res/layout/join_contact_picker.xml
@@ -24,20 +24,22 @@
         android:layout_width="match_parent"
         android:layout_height="0dip"
         android:layout_weight="1"
-        android:id="@+id/list_container">
-    </FrameLayout>
+        android:id="@+id/list_container" />
 
     <View
+        android:id="@+id/divider"
         android:layout_width="match_parent"
         android:layout_height="1dip"
-        android:layout_marginLeft="16dip"
-        android:layout_marginRight="16dip"
+        android:layout_marginLeft="?attr/contact_browser_list_padding_left"
+        android:layout_marginRight="?attr/contact_browser_list_padding_right"
         android:background="?android:attr/dividerHorizontal" />
 
     <LinearLayout
         style="?android:attr/buttonBarStyle"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content">
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="?attr/contact_browser_list_padding_left"
+        android:layout_marginRight="?attr/contact_browser_list_padding_right">
         <Button
             style="?android:attr/buttonBarButtonStyle"
             android:id="@+id/cancel"
diff --git a/res/layout/join_contact_picker_list_content.xml b/res/layout/join_contact_picker_list_content.xml
index 0d2a089..9e72c31 100644
--- a/res/layout/join_contact_picker_list_content.xml
+++ b/res/layout/join_contact_picker_list_content.xml
@@ -19,33 +19,30 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:paddingTop="8dip"
     android:orientation="vertical">
 
     <TextView
         android:id="@+id/join_contact_blurb"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:paddingLeft="10dip"
-        android:paddingTop="12dip"
-        android:paddingBottom="12dip"
-        android:layout_marginLeft="12dip"
-        android:layout_marginRight="12dip"
+        android:paddingLeft="16dip"
+        android:paddingRight="16dip"
         android:maxLines="2"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-        android:textColor="?android:attr/textColorSecondary" />
+        android:textAppearance="?android:attr/textAppearanceMedium" />
 
     <FrameLayout
         android:id="@+id/pinned_header_list_layout"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_marginLeft="48dip"
-        android:layout_marginRight="48dip">
-
+        android:layout_height="match_parent">
         <view
             class="com.android.contacts.list.ContactEntryListView"
             android:id="@android:id/list"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:fastScrollEnabled="true" />
+            android:layout_marginLeft="?attr/contact_browser_list_padding_left"
+            android:layout_marginRight="?attr/contact_browser_list_padding_right"
+            android:fastScrollEnabled="true"
+            android:scrollbarStyle="outsideOverlay" />
     </FrameLayout>
 </LinearLayout>
diff --git a/res/layout/join_contact_picker_section.xml b/res/layout/join_contact_picker_section.xml
index 95ec107..260ea2d 100644
--- a/res/layout/join_contact_picker_section.xml
+++ b/res/layout/join_contact_picker_section.xml
@@ -22,12 +22,12 @@
 
     <TextView
         android:id="@+id/text"
-        android:layout_height="32dip"
         android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingLeft="?attr/list_item_header_text_indent"
+        android:minHeight="16dip"
         android:textAppearance="?android:attr/textAppearanceSmall"
-        android:textColor="?android:attr/textColorSecondary"
         android:gravity="center_vertical" />
 
-    <View
-        style="@style/SectionDivider" />
+    <View style="@style/SectionDivider" />
 </LinearLayout>
diff --git a/res/layout/playback_layout.xml b/res/layout/playback_layout.xml
index bb32014..161c5bd 100644
--- a/res/layout/playback_layout.xml
+++ b/res/layout/playback_layout.xml
@@ -1,125 +1,119 @@
 <?xml version="1.0" encoding="utf-8"?>
-<LinearLayout
+<RelativeLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:background="@color/voicemail_playback_ui_background"
 >
-    <RelativeLayout
+    <!-- Mute, playback, trash buttons. -->
+    <LinearLayout
+        android:id="@+id/buttons_linear_layout"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:background="@color/voicemail_playback_ui_background"
+        android:orientation="horizontal"
+        android:layout_alignParentTop="true"
     >
-        <!-- Mute, playback, trash buttons. -->
         <LinearLayout
-            android:id="@+id/buttons_linear_layout"
+            android:layout_width="match_parent"
+            android:layout_height="58dip"
+            android:layout_marginRight="2dip"
+            android:background="@drawable/dialpad_background"
+            android:layout_weight="1"
+        >
+            <ImageButton
+                android:id="@+id/playback_start_stop"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:background="@drawable/btn_dial"
+                android:src="@drawable/ic_hold_pause_holo_dark"
+            />
+        </LinearLayout>
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="58dip"
+            android:layout_marginLeft="2dip"
+            android:background="@drawable/dialpad_background"
+            android:layout_weight="1"
+        >
+            <ImageButton
+                android:id="@+id/playback_speakerphone"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:background="@drawable/btn_dial"
+                android:src="@drawable/ic_sound_holo_dark"
+            />
+        </LinearLayout>
+    </LinearLayout>
+    <RelativeLayout
+        android:id="@+id/seek_container"
+        android:layout_width="match_parent"
+        android:layout_height="80dip"
+        android:background="@drawable/dialpad_background"
+        android:layout_below="@id/buttons_linear_layout"
+        android:layout_marginTop="4dip"
+    >
+        <!-- SeekBar left-right margin decreased from redlines 72dip by 8dip to account for
+             half thumb width (thumb is 16dip).
+             Vertically, SeekBar and rate buttons should be below centre, position achieved by
+             making them centred but giving a difference between top and bottom padding,
+             difference is currently 10dip. -->
+        <SeekBar
+            android:id="@+id/playback_seek"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:orientation="horizontal"
+            android:progressDrawable="@drawable/seekbar_drawable"
+            android:thumb="@drawable/seek_bar_thumb"
+            android:thumbOffset="8dip"
+            android:progress="0"
+            android:paddingLeft="8dip"
+            android:paddingRight="8dip"
+            android:paddingTop="30dip"
+            android:paddingBottom="20dip"
+            android:layout_marginRight="64dip"
+            android:layout_marginLeft="64dip"
+            android:max="0"
+            android:layout_centerVertical="true"
+        />
+        <TextView
+            android:id="@+id/playback_position_text"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:textSize="14sp"
             android:layout_alignParentTop="true"
-        >
-            <LinearLayout
-                android:layout_width="match_parent"
-                android:layout_height="58dip"
-                android:layout_marginRight="2dip"
-                android:background="@drawable/dialpad_background"
-                android:layout_weight="1"
-            >
-                <ImageButton
-                    android:id="@+id/playback_start_stop"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent"
-                    android:background="@drawable/btn_dial"
-                    android:src="@drawable/ic_hold_pause_holo_dark"
-                />
-            </LinearLayout>
-            <LinearLayout
-                android:layout_width="match_parent"
-                android:layout_height="58dip"
-                android:layout_marginLeft="2dip"
-                android:background="@drawable/dialpad_background"
-                android:layout_weight="1"
-            >
-                <ImageButton
-                    android:id="@+id/playback_speakerphone"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent"
-                    android:background="@drawable/btn_dial"
-                    android:src="@drawable/ic_sound_holo_dark"
-                />
-            </LinearLayout>
-        </LinearLayout>
-        <RelativeLayout
-            android:id="@+id/seek_container"
-            android:layout_width="match_parent"
-            android:layout_height="80dip"
-            android:background="@drawable/dialpad_background"
-            android:layout_below="@id/buttons_linear_layout"
-            android:layout_marginTop="4dip"
-        >
-            <!-- SeekBar left-right margin decreased from redlines 72dip by 8dip to account for
-                 half thumb width (thumb is 16dip).
-                 Vertically, SeekBar and rate buttons should be below centre, position achieved by
-                 making them centred but giving a difference between top and bottom padding,
-                 difference is currently 10dip. -->
-            <SeekBar
-                android:id="@+id/playback_seek"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:progressDrawable="@drawable/seekbar_drawable"
-                android:thumb="@drawable/seek_bar_thumb"
-                android:thumbOffset="8dip"
-                android:progress="0"
-                android:paddingLeft="8dip"
-                android:paddingRight="8dip"
-                android:paddingTop="30dip"
-                android:paddingBottom="20dip"
-                android:layout_marginRight="64dip"
-                android:layout_marginLeft="64dip"
-                android:max="0"
-                android:layout_centerVertical="true"
-            />
-            <TextView
-                android:id="@+id/playback_position_text"
-                android:layout_height="wrap_content"
-                android:layout_width="wrap_content"
-                android:textSize="14sp"
-                android:layout_alignParentTop="true"
-                android:layout_centerHorizontal="true"
-                android:layout_marginTop="10dip"
-            />
-            <TextView
-                android:id="@+id/playback_speed_text"
-                android:layout_height="wrap_content"
-                android:layout_width="wrap_content"
-                android:textSize="14sp"
-                android:layout_alignParentTop="true"
-                android:layout_centerHorizontal="true"
-                android:layout_marginTop="10dip"
-                android:alpha="0"
-            />
-            <ImageButton
-                android:id="@+id/rate_decrease_button"
-                android:src="@drawable/ic_minus_holo_dark"
-                android:layout_width="64dip"
-                android:layout_height="wrap_content"
-                android:background="@drawable/btn_dial"
-                android:paddingBottom="19dip"
-                android:paddingTop="29dip"
-                android:layout_alignParentLeft="true"
-                android:layout_centerVertical="true"
-            />
-            <ImageButton
-                android:id="@+id/rate_increase_button"
-                android:src="@drawable/ic_plus_holo_dark"
-                android:layout_width="64dip"
-                android:layout_height="wrap_content"
-                android:background="@drawable/btn_dial"
-                android:paddingBottom="19dip"
-                android:paddingTop="29dip"
-                android:layout_alignParentRight="true"
-                android:layout_centerVertical="true"
-            />
-        </RelativeLayout>
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="10dip"
+        />
+        <TextView
+            android:id="@+id/playback_speed_text"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:textSize="14sp"
+            android:layout_alignParentTop="true"
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="10dip"
+            android:alpha="0"
+        />
+        <ImageButton
+            android:id="@+id/rate_decrease_button"
+            android:src="@drawable/ic_minus_holo_dark"
+            android:layout_width="64dip"
+            android:layout_height="wrap_content"
+            android:background="@drawable/btn_dial"
+            android:paddingBottom="19dip"
+            android:paddingTop="29dip"
+            android:layout_alignParentLeft="true"
+            android:layout_centerVertical="true"
+        />
+        <ImageButton
+            android:id="@+id/rate_increase_button"
+            android:src="@drawable/ic_plus_holo_dark"
+            android:layout_width="64dip"
+            android:layout_height="wrap_content"
+            android:background="@drawable/btn_dial"
+            android:paddingBottom="19dip"
+            android:paddingTop="29dip"
+            android:layout_alignParentRight="true"
+            android:layout_centerVertical="true"
+        />
     </RelativeLayout>
-</LinearLayout>
+</RelativeLayout>
diff --git a/res/layout/social_widget.xml b/res/layout/social_widget.xml
index ddcd995..e9847f9 100644
--- a/res/layout/social_widget.xml
+++ b/res/layout/social_widget.xml
@@ -48,14 +48,14 @@
             android:layout_height="match_parent"
             android:layout_weight="1"
             android:background="@drawable/bg_status_contact_widget"
-            android:layout_marginTop="4dip"
+            android:layout_marginTop="@dimen/widget_snippet_top_margin"
             android:layout_marginRight="16dip"
-            android:layout_marginBottom="7dip"
+            android:layout_marginBottom="@dimen/widget_snippet_bottom_margin"
             android:layout_marginLeft="0dip"
             android:paddingLeft="47dip"
             android:paddingRight="8dip"
-            android:paddingTop="3dip"
-            android:paddingBottom="6dip">
+            android:paddingTop="@dimen/widget_snippet_top_padding"
+            android:paddingBottom="@dimen/widget_snippet_bottom_padding">
 
             <TextView
                 android:id="@+id/name_and_snippet"
@@ -75,17 +75,6 @@
                 android:gravity="center"
                 android:textColor="#FFFFFFFF"
                 android:textSize="@dimen/widget_text_size_name" />
-
-            <TextView
-                android:id="@+id/status_date"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignParentRight="true"
-                android:layout_alignParentBottom="true"
-                android:background="@drawable/statusbox_attribute_holo"
-                android:textSize="13sp"
-                android:textColor="#FF444444"
-                android:visibility="gone" />
         </RelativeLayout>
     </LinearLayout>
 </FrameLayout>
\ No newline at end of file
diff --git a/res/layout/updates_title.xml b/res/layout/updates_title.xml
new file mode 100644
index 0000000..4b706cc
--- /dev/null
+++ b/res/layout/updates_title.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 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"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingLeft="@dimen/detail_item_side_margin"
+    android:paddingRight="@dimen/detail_item_side_margin"
+    android:orientation="vertical">
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="24dip"
+        android:text="@string/recent_updates"
+        android:textColor="@color/detail_kind_title_color"
+        android:textStyle="bold"
+        android:singleLine="true"
+        android:ellipsize="end"
+        android:paddingLeft="8dip"
+        android:paddingTop="5dip"
+        android:paddingBottom="2dip" />
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="2dip"
+        android:background="@color/detail_kind_title_color"/>
+
+</LinearLayout>
diff --git a/res/layout/user_profile_button.xml b/res/layout/user_profile_button.xml
index 4937d7b..8735f5a 100644
--- a/res/layout/user_profile_button.xml
+++ b/res/layout/user_profile_button.xml
@@ -18,11 +18,13 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
+    android:minHeight="@dimen/contact_browser_list_item_photo_size"
+    android:layout_marginLeft="?attr/list_item_padding_left"
+    android:layout_marginRight="?attr/list_item_padding_right"
+    android:paddingLeft="?attr/list_item_header_text_indent"
     android:background="?android:attr/selectableItemBackground"
     android:singleLine="true"
     android:text="@string/profile_display_name"
     android:ellipsize="end"
-    android:minHeight="@dimen/contact_browser_list_item_photo_size"
     android:gravity="left|center_vertical"
-    android:paddingLeft="@dimen/contact_browser_list_item_text_indent"
     android:textAppearance="?android:attr/textAppearanceMedium" />
diff --git a/res/layout/user_profile_header.xml b/res/layout/user_profile_header.xml
index 7c82ea4..ff01a11 100644
--- a/res/layout/user_profile_header.xml
+++ b/res/layout/user_profile_header.xml
@@ -16,15 +16,19 @@
 
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:paddingTop="@dimen/contact_browser_list_top_margin"
+    android:id="@+id/user_profile_header"
     android:orientation="vertical"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content" >
+    android:layout_height="wrap_content"
+    android:minHeight="?attr/list_item_header_height"
+    android:paddingTop="@dimen/contact_browser_list_top_margin"
+    android:paddingLeft="?attr/list_item_padding_left"
+    android:paddingRight="?attr/list_item_padding_right" >
 
     <LinearLayout
         android:orientation="horizontal"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content" >
+        android:layout_height="wrap_content">
 
         <TextView
             android:id="@+id/profile_title"
@@ -37,7 +41,7 @@
             android:gravity="left|center_vertical"
             android:layout_weight="1"
             android:textAppearance="?android:attr/textAppearanceSmall"
-            android:paddingLeft="@dimen/contact_browser_list_item_text_indent"
+            android:paddingLeft="?attr/list_item_text_indent"
             android:textColor="@color/people_app_theme_color" />
 
         <TextView
@@ -55,6 +59,6 @@
     <View
         android:background="@color/people_app_theme_color"
         android:layout_width="match_parent"
-        android:layout_height="1dip" />
+        android:layout_height="?attr/list_item_header_underline_height" />
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/res/menu/call_log_options.xml b/res/menu/call_log_options.xml
index b50869a..c62be77 100644
--- a/res/menu/call_log_options.xml
+++ b/res/menu/call_log_options.xml
@@ -26,6 +26,11 @@
         android:showAsAction="withText" />
 
     <item
+        android:id="@+id/show_all_calls"
+        android:title="@string/menu_show_all_calls"
+        android:showAsAction="withText" />
+
+    <item
         android:id="@+id/menu_call_settings_call_log"
         android:title="@string/call_settings"
         android:icon="@drawable/ic_menu_settings_holo_light"
diff --git a/res/values-sw580dp-w720dp/styles.xml b/res/values-sw580dp-w720dp/styles.xml
index ff50d45..4314c80 100644
--- a/res/values-sw580dp-w720dp/styles.xml
+++ b/res/values-sw580dp-w720dp/styles.xml
@@ -37,10 +37,16 @@
         <item name="list_item_prefix_highlight_color">#729a27</item>
         <item name="list_item_header_text_indent">8dip</item>
         <item name="list_item_header_text_color">@color/people_app_theme_color</item>
-        <item name="list_item_header_height">26dip</item>
+        <item name="list_item_header_height">24dip</item>
         <item name="list_item_header_text_size">14sp</item>
         <item name="list_item_header_underline_color">@color/people_app_theme_color</item>
+        <item name="list_item_header_underline_height">1dip</item>
+        <item name="list_item_contacts_count_text_color">@color/contact_count_text_color</item>
+        <item name="list_item_contacts_count_text_size">12sp</item>
         <item name="contact_filter_popup_width">320dip</item>
+        <item name="contact_browser_list_padding_left">0dip</item>
+        <item name="contact_browser_list_padding_right">0dip</item>
+        <item name="list_item_text_indent">@dimen/contact_browser_list_item_text_indent</item>
         <!-- Favorites -->
         <item name="favorites_padding_bottom">0dip</item>
     </style>
diff --git a/res/values-sw580dp/dimens.xml b/res/values-sw580dp/dimens.xml
index 91842d6..42a8314 100644
--- a/res/values-sw580dp/dimens.xml
+++ b/res/values-sw580dp/dimens.xml
@@ -42,7 +42,11 @@
     <dimen name="contact_browser_list_top_margin">16dip</dimen>
     <dimen name="contact_browser_list_header_left_margin">@dimen/list_visible_scrollbar_padding</dimen>
     <dimen name="contact_browser_list_header_right_margin">24dip</dimen>
-    <dimen name="contact_browser_list_left_margin">0dip</dimen>
-    <dimen name="contact_browser_list_right_margin">0dip</dimen>
     <dimen name="list_visible_scrollbar_padding">48dip</dimen>
+
+    <!-- Margins and padding for text in widget -->
+    <dimen name="widget_snippet_top_margin">5dip</dimen>
+    <dimen name="widget_snippet_bottom_margin">6dip</dimen>
+    <dimen name="widget_snippet_top_padding">6dip</dimen>
+    <dimen name="widget_snippet_bottom_padding">3dip</dimen>
 </resources>
diff --git a/res/values-sw580dp/styles.xml b/res/values-sw580dp/styles.xml
index a386e57..efbbde2 100644
--- a/res/values-sw580dp/styles.xml
+++ b/res/values-sw580dp/styles.xml
@@ -19,7 +19,7 @@
         <item name="android:actionBarTabStyle">@style/ContactsActionBarTabView</item>
         <item name="android:textColorPrimary">@color/primary_text_color</item>
         <item name="android:textColorSecondary">@color/secondary_text_color</item>
-        <item name="list_item_height">66dip</item>
+        <item name="list_item_height">?android:attr/listPreferredItemHeight</item>
         <item name="activated_background">@drawable/list_item_activated_background</item>
         <item name="section_header_background">@drawable/list_title_holo</item>
         <item name="list_item_divider">?android:attr/listDivider</item>
@@ -40,29 +40,51 @@
         <item name="list_item_header_text_color">@color/people_app_theme_color</item>
         <item name="list_item_header_height">26dip</item>
         <item name="list_item_header_underline_color">@color/people_app_theme_color</item>
+        <item name="list_item_header_underline_height">1dip</item>
+        <item name="list_item_contacts_count_text_color">@color/contact_count_text_color</item>
+        <item name="list_item_contacts_count_text_size">12sp</item>
         <item name="contact_filter_popup_width">320dip</item>
+        <item name="contact_browser_list_padding_left">0dip</item>
+        <item name="contact_browser_list_padding_right">0dip</item>
+        <item name="list_item_text_indent">@dimen/contact_browser_list_item_text_indent</item>
         <!-- Favorites -->
         <item name="favorites_padding_bottom">0dip</item>
     </style>
 
     <style name="ContactPickerTheme" parent="@android:Theme.Holo.Light.Dialog">
-        <item name="list_item_height">66dip</item>
+        <item name="list_item_height">?android:attr/listPreferredItemHeight</item>
         <item name="section_header_background">@drawable/list_title_holo</item>
         <item name="list_item_divider">?android:attr/listDivider</item>
         <item name="list_item_padding_top">0dip</item>
-        <item name="list_item_padding_right">24dip</item>
+        <item name="list_item_padding_right">0dip</item>
         <item name="list_item_padding_bottom">0dip</item>
         <item name="list_item_padding_left">0dip</item>
-        <item name="list_item_gap_between_image_and_text">16dip</item>
+        <item name="list_item_gap_between_image_and_text">8dip</item>
         <item name="list_item_gap_between_label_and_data">5dip</item>
         <item name="list_item_call_button_padding">14dip</item>
         <item name="list_item_vertical_divider_margin">5dip</item>
-        <item name="list_item_presence_icon_margin">30dip</item>
+        <item name="list_item_presence_icon_margin">18dip</item>
         <item name="list_item_photo_size">64dip</item>
         <item name="list_item_profile_photo_size">80dip</item>
-        <item name="list_item_header_text_indent">77dip</item>
-        <item name="list_item_header_text_color">?color/section_header_text_color</item>
+        <item name="list_item_header_text_indent">8dip</item>
         <item name="list_item_header_text_size">14sp</item>
+        <item name="list_item_header_text_color">@color/people_app_theme_color</item>
+        <item name="list_item_header_height">24dip</item>
+        <item name="list_item_header_underline_color">@color/people_app_theme_color</item>
+        <item name="list_item_header_underline_height">1dip</item>
+        <item name="list_item_contacts_count_text_color">@color/contact_count_text_color</item>
+        <item name="list_item_contacts_count_text_size">12sp</item>
+        <item name="contact_filter_popup_width">320dip</item>
+        <item name="contact_browser_list_padding_left">16dip</item>
+        <item name="contact_browser_list_padding_right">0dip</item>
+    </style>
+    <style name="ContactPickerLayout" parent="ContactPickerTheme">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">480dip</item>
+    </style>
+    <style name="JoinContactActivityTheme" parent="ContactPickerTheme" >
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">480dip</item>
     </style>
 
     <style name="ContactListFilterTheme" parent="@android:Theme.Holo.Light.Dialog">
@@ -74,11 +96,6 @@
         <item name="android:layout_height">400dip</item>
     </style>
 
-    <style name="ContactPickerLayout" parent="ContactPickerTheme">
-        <item name="android:layout_width">480dip</item>
-        <item name="android:layout_height">match_parent</item>
-    </style>
-
     <style name="ContactDetailActivityTheme" parent="@android:Theme.Dialog">
         <item name="android:windowContentOverlay">@null</item>
     </style>
@@ -86,7 +103,7 @@
     <style name="DirectoryHeader" parent="PeopleTheme">
         <item name="android:paddingTop">0dip</item>
         <item name="android:paddingBottom">0dip</item>
-        <item name="android:background">@drawable/directory_bg_holo</item>
+        <item name="android:background">@android:color/transparent</item>
     </style>
 
     <style name="NonPhoneDialogTheme" parent="@android:Theme.Holo.Light.Dialog">
@@ -102,8 +119,4 @@
         <item name="android:windowNoDisplay">true</item>
         <item name="android:windowIsFloating">true</item>
     </style>
-
-    <style name="GroupBrowseListItem">
-        <item name="android:background">@drawable/list_item_activated_background</item>
-    </style>
 </resources>
diff --git a/res/values-w470dp/strings.xml b/res/values-w470dp/strings.xml
index 8dc9c09..17934d7 100644
--- a/res/values-w470dp/strings.xml
+++ b/res/values-w470dp/strings.xml
@@ -14,5 +14,5 @@
      limitations under the License.
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="recent_updates">Updates</string>
-</resources>
\ No newline at end of file
+    <string name="recent_updates">Recent updates</string>
+</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 0f7b62d..7bec43a 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -68,6 +68,8 @@
 
     <declare-styleable name="ContactBrowser">
         <attr name="contact_filter_popup_width" format="dimension"/>
+        <attr name="contact_browser_list_padding_left" format="dimension"/>
+        <attr name="contact_browser_list_padding_right" format="dimension"/>
     </declare-styleable>
 
     <declare-styleable name="ContactListItemView">
diff --git a/res/values/colors.xml b/res/values/colors.xml
index a277124..1e47948 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -87,7 +87,6 @@
     <color name="dialtacts_secondary_text_color">#888888</color>
 
     <!-- Colors in the contact browser list -->
-    <color name="contact_browser_list_bk_color">#EEEEEE</color>
     <color name="contact_count_text_color">#AAAAAA</color>
 
     <!-- Color of the text of the tab carousel in the contact details  -->
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 69441fd..81b962f 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -163,6 +163,12 @@
     <!-- Font size used for the social status in the widget -->
     <dimen name="widget_text_size_snippet">13sp</dimen>
 
+    <!-- Margins and padding for text in widget -->
+    <dimen name="widget_snippet_top_margin">4dip</dimen>
+    <dimen name="widget_snippet_bottom_margin">7dip</dimen>
+    <dimen name="widget_snippet_top_padding">3dip</dimen>
+    <dimen name="widget_snippet_bottom_padding">6dip</dimen>
+
     <!-- Minimum width of the filter selector in the action bar -->
     <dimen name="action_bar_filter_min_width">100dip</dimen>
 
@@ -210,8 +216,6 @@
     <!-- contact browser list margins -->
     <dimen name="contact_browser_list_header_left_margin">16dip</dimen>
     <dimen name="contact_browser_list_header_right_margin">@dimen/list_visible_scrollbar_padding</dimen>
-    <dimen name="contact_browser_list_left_margin">16dip</dimen>
-    <dimen name="contact_browser_list_right_margin">0dip</dimen>
     <dimen name="contact_browser_list_item_photo_size">64dip</dimen>
     <dimen name="contact_browser_list_item_text_indent">8dip</dimen>
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0c0a20a..c7a2bc7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -143,13 +143,11 @@
     <!-- Menu item (in the action bar) that creates a new group [CHAR LIMIT=12] -->
     <string name="menu_new_group_action_bar">New</string>
 
-    <!-- Title of the confirmation dialog for separating contacts into multiple instances  -->
-    <string name="splitConfirmation_title">Separate Contact</string>
+    <!-- Title of the confirmation dialog for separating contacts into multiple instances [CHAR LIMIT=20] -->
+    <string name="splitConfirmation_title">Separate contact</string>
 
-    <!-- Confirmation dialog for separating contacts into multiple instances  -->
-    <string name="splitConfirmation">Are you sure you want to separate this single contact
-        into multiple contacts: one for each set of contact information that was joined into it?
-    </string>
+    <!-- Confirmation dialog for separating contacts into multiple instances [CHAR LIMIT=NONE] -->
+    <string name="splitConfirmation">Are you sure you want to separate this single contact into multiple contacts?</string>
 
     <!-- Menu item that joins an aggregate with another aggregate -->
     <string name="menu_joinAggregate">Join</string>
@@ -903,8 +901,8 @@
     <!-- Dialog title shown when a user confirms whether he/she export Contact data -->
     <string name="confirm_export_title">Confirm export</string>
 
-    <!-- Dialog message shown when a user confirms whether he/she export Contact data -->
-    <string name="confirm_export_message">Are you sure you want to export your contact list to \"<xliff:g id="vcard_filename">%s</xliff:g>\"?</string>
+    <!-- Dialog message shown when a user confirms whether he/she export Contact data [CHAR LIMIT=NONE] -->
+    <string name="confirm_export_message">Export your contact list to file \"<xliff:g id="vcard_filename">%s</xliff:g>\"?</string>
 
     <!-- Dialog title shown when exporting Contact data failed -->
     <string name="exporting_contact_failed_title">Failed to export contact data</string>
@@ -1265,14 +1263,17 @@
     <string name="name_phonetic">Phonetic name</string>
 
     <!-- Title for the list of all contact details that come from third-party sources (including a corporate directory) [CHAR LIMIT=20] -->
-    <string name="network">Network</string>
+    <string name="connections">Connections</string>
 
-    <!-- Label of the button to open the "more networks" popup where the user can invite a contact to other social networks or services [CHAR LIMIT=32] -->
-    <string name="more_networks_button">More networks</string>
+    <!-- Label of the button to open the "add connection" popup where the user can invite a contact to other social networks or services [CHAR LIMIT=32] -->
+    <string name="add_connection_button">Add connection</string>
 
     <!-- Section title for the page containing the contact's social updates on the contact card [CHAR LIMIT=20]-->
     <string name="recent_updates">Recent</string>
 
+    <!-- Label that contains the social update from a contact on the contact card. The text should appear as a quotation. [CHAR LIMIT=5] -->
+    <string name="recent_updates_tab_text">\"<xliff:g id="update_text">%s</xliff:g>\"</string>
+
     <!-- String describing which account type a contact came from when editing it -->
     <string name="account_type_format"><xliff:g id="source" example="Gmail">%1$s</xliff:g> contact</string>
 
@@ -1444,7 +1445,7 @@
     <string name="directory_search_label">Directory</string>
 
     <!-- The label in section header in the contact list for a local contacts [CHAR LIMIT=128] -->
-    <string name="local_search_label">Contacts</string>
+    <string name="local_search_label">All contacts</string>
 
     <!-- Toast shown when creating a personal copy of a contact [CHAR LIMIT=100] -->
     <string name="toast_making_personal_copy">Creating a personal copy</string>
@@ -1480,7 +1481,7 @@
     <string name="activity_title_contacts_filter">Contacts to display</string>
 
     <!-- Menu item for the settings activity [CHAR LIMIT=64] -->
-    <string name="menu_settings">Display Options</string>
+    <string name="menu_settings">Display options</string>
 
     <!-- The preference section title for contact display options [CHAR LIMIT=128] -->
     <string name="preference_displayOptions">Display options</string>
@@ -1498,6 +1499,9 @@
     <!-- Button to add a phone number to contacts [CHAR LIMIT=25] -->
     <string name="non_phone_add_to_contacts">Add to contacts</string>
 
+    <!-- Title of the activity that allows the user to confirm the addition of a detail to 1 existing contact [CHAR LIMIT=25] -->
+    <string name="activity_title_confirm_add_detail">Add to contact</string>
+
     <!-- Button to close without add a phone number to contacts [CHAR LIMIT=25] -->
     <string name="non_phone_close">Close</string>
 
@@ -1601,7 +1605,7 @@
     <string name="profile_display_name">Set up my profile</string>
 
     <!-- Label to instruct the user to type in a contact's name to add the contact as a member of the current group. [CHAR LIMIT=64] -->
-    <string name="enter_contact_name">Enter contact\'s name</string>
+    <string name="enter_contact_name">Type person\'s name</string>
 
     <!-- Button to view the updates from the current group on the group detail page [CHAR LIMIT=20] -->
     <string name="view_updates_from_group">View updates</string>
@@ -1631,6 +1635,12 @@
     <!-- Message to display before we have prepared the media player, i.e. before we know duration. [CHAR LIMIT=40] -->
     <string name="voicemail_buffering">buffering...</string>
 
+    <!-- Message to display whilst we are waiting for the content to be fetched. [CHAR LIMIT=40] -->
+    <string name="voicemail_fetching_content">fetching voicemail...</string>
+
+    <!-- Message to display if we fail to get content within a suitable time period. [CHAR LIMIT=40] -->
+    <string name="voicemail_fetching_timout">failed to fetch voicemail</string>
+
     <!-- The header in the call log used to identify missed calls and voicemail that have not yet been consumed [CHAR LIMIT=10] -->
     <string name="call_log_new_header">New</string>
 
@@ -1682,6 +1692,9 @@
     <!-- Menu item used to show only voicemails in the call log. [CHAR LIMIT=30] -->
     <string name="menu_show_voicemails_only">Show voicemails only</string>
 
+    <!-- Menu item used to show all calls in the call log. [CHAR LIMIT=30] -->
+    <string name="menu_show_all_calls">Show all calls</string>
+
     <!--  Used to display as default status when the contact is available for chat [CHAR LIMIT=19] -->
     <string name="status_available">Available</string>
 
diff --git a/res/values/styles.xml b/res/values/styles.xml
index d202a0f..84c3d15 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -42,9 +42,11 @@
         <item name="list_item_header_text_color">@color/people_app_theme_color</item>
         <item name="list_item_header_text_size">12sp</item>
         <item name="list_item_header_height">24dip</item>
-        <item name="list_item_header_underline_height">1px</item>
+        <item name="list_item_header_underline_height">1dip</item>
         <item name="list_item_header_underline_color">@color/people_app_theme_color</item>
         <item name="contact_filter_popup_width">320dip</item>
+        <item name="contact_browser_list_padding_left">16dip</item>
+        <item name="contact_browser_list_padding_right">0dip</item>
         <item name="list_item_text_indent">@dimen/contact_browser_list_item_text_indent</item>
         <!-- CallLog -->
         <item name="call_log_primary_text_color">#FFFFFF</item>
@@ -144,17 +146,18 @@
         <item name="list_item_photo_size">@dimen/contact_browser_list_item_photo_size</item>
         <item name="list_item_profile_photo_size">70dip</item>
         <item name="list_item_prefix_highlight_color">#729a27</item>
-        <item name="list_item_header_text_indent">@dimen/contact_browser_list_item_text_indent</item>
         <item name="list_item_header_text_color">@color/people_app_theme_color</item>
         <item name="list_item_header_text_size">14dip</item>
         <item name="list_item_header_height">26dip</item>
         <item name="list_item_header_underline_height">1dip</item>
         <item name="list_item_header_underline_color">@color/people_app_theme_color</item>
         <item name="list_item_contacts_count_text_color">@color/contact_count_text_color</item>
+        <item name="list_item_header_text_indent">8dip</item>
         <item name="contact_filter_popup_width">320dip</item>
+        <item name="contact_browser_list_padding_left">16dip</item>
+        <item name="contact_browser_list_padding_right">0dip</item>
         <item name="list_item_text_indent">@dimen/contact_browser_list_item_text_indent</item>
-        <item name="list_item_contacts_count_text_size">12dip</item>
-        list_item_contacts_count_text_size
+        <item name="list_item_contacts_count_text_size">12sp</item>
         <!-- Favorites -->
         <item name="favorites_padding_bottom">0dip</item>
     </style>
@@ -190,30 +193,19 @@
         <item name="list_item_photo_size">@dimen/contact_browser_list_item_photo_size</item>
         <item name="list_item_profile_photo_size">70dip</item>
         <item name="list_item_prefix_highlight_color">#729a27</item>
-        <item name="list_item_header_text_indent">56dip</item>
         <item name="list_item_header_text_color">?color/section_header_text_color</item>
         <item name="list_item_header_text_size">14sp</item>
+        <item name="list_item_header_text_indent">8dip</item>
         <item name="contact_filter_popup_width">320dip</item>
+        <item name="contact_browser_list_padding_left">16dip</item>
+        <item name="contact_browser_list_padding_right">0dip</item>
     </style>
 
-    <style name="ContactPickerTheme" parent="@android:Theme.Holo.Light">
-        <item name="section_header_background">@drawable/section_header</item>
-        <item name="list_item_divider">?android:attr/listDivider</item>
-        <item name="list_item_padding_top">4dip</item>
-        <item name="list_item_padding_right">11dip</item>
-        <item name="list_item_padding_bottom">4dip</item>
-        <item name="list_item_padding_left">4dip</item>
-        <item name="list_item_gap_between_image_and_text">8dip</item>
-        <item name="list_item_gap_between_label_and_data">5dip</item>
-        <item name="list_item_call_button_padding">14dip</item>
-        <item name="list_item_vertical_divider_margin">5dip</item>
-        <item name="list_item_presence_icon_margin">5dip</item>
-        <item name="list_item_photo_size">@dimen/contact_browser_list_item_photo_size</item>
-        <item name="list_item_profile_photo_size">70dip</item>
-        <item name="list_item_prefix_highlight_color">#729a27</item>
-        <item name="list_item_header_text_indent">56dip</item>
-        <item name="list_item_header_text_color">?color/section_header_text_color</item>
-        <item name="list_item_header_text_size">14sp</item>
+    <style name="ContactPickerTheme" parent="@style/PeopleTheme">
+    </style>
+    <style name="ContactPickerLayout" parent="ContactPickerTheme">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">match_parent</item>
     </style>
 
     <style name="JoinContactActivityTheme" parent="ContactPickerTheme" >
@@ -225,11 +217,6 @@
     <style name="ContactListFilterTheme" parent="@android:Theme.Holo.Light">
     </style>
 
-    <style name="ContactPickerLayout" parent="ContactPickerTheme">
-        <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_height">match_parent</item>
-    </style>
-
     <style name="CustomContactListFilterView" parent="ContactListFilterTheme">
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">match_parent</item>
@@ -247,7 +234,7 @@
 
     <style name="SectionDivider">
         <item name="android:background">#7e7e87</item>
-        <item name="android:layout_height">2dip</item>
+        <item name="android:layout_height">1dip</item>
         <item name="android:layout_width">match_parent</item>
     </style>
 
@@ -264,9 +251,6 @@
         <item name="android:layout_gravity">center_vertical</item>
     </style>
 
-    <style name="GroupBrowseListItem">
-    </style>
-
     <style name="DialtactsDigitsTextAppearance">
         <item name="android:maxLines">1</item>
         <item name="android:scrollHorizontally">true</item>
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index aa52d91..85e0ff7 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -198,6 +198,7 @@
      * playback.  If it doesn't, then hide the voicemail ui.
      */
     private void optionallyHandleVoicemail() {
+        View voicemailContainer = findViewById(R.id.voicemail_container);
         if (hasVoicemail()) {
             // Has voicemail: add the voicemail fragment.  Add suitable arguments to set the uri
             // to play and optionally start the playback.
@@ -209,6 +210,7 @@
                 fragmentArguments.putBoolean(EXTRA_VOICEMAIL_START_PLAYBACK, true);
             }
             playbackFragment.setArguments(fragmentArguments);
+            voicemailContainer.setVisibility(View.VISIBLE);
             getFragmentManager().beginTransaction()
                     .add(R.id.voicemail_container, playbackFragment).commit();
             mAsyncQueryHandler.startVoicemailStatusQuery(getVoicemailUri());
@@ -216,6 +218,7 @@
         } else {
             // No voicemail uri: hide the status view.
             mStatusMessageView.setVisibility(View.GONE);
+            voicemailContainer.setVisibility(View.GONE);
         }
     }
 
@@ -409,7 +412,8 @@
                             getString(R.string.description_call, nameOrNumber));
 
                     // Only show a label if the number is shown and it is not a SIP address.
-                    if (!TextUtils.isEmpty(firstDetails.number)
+                    if (!TextUtils.isEmpty(firstDetails.name)
+                            && !TextUtils.isEmpty(firstDetails.number)
                             && !PhoneNumberUtils.isUriNumber(firstDetails.number.toString())) {
                         entry.label = Phone.getTypeLabel(mResources, firstDetails.numberType,
                                 firstDetails.numberLabel);
@@ -550,7 +554,6 @@
         public final String primaryDescription;
 
         public CharSequence label = null;
-        public String number = null;
         /** Icon for the secondary action. */
         public int secondaryIcon = 0;
         /** Intent for the secondary action. If not null, an icon must be defined. */
@@ -583,7 +586,7 @@
 
         ImageView icon = (ImageView) convertView.findViewById(R.id.call_and_sms_icon);
         View divider = convertView.findViewById(R.id.call_and_sms_divider);
-        TextView text = (TextView) convertView.findViewById(R.id.call_and_sms_text1);
+        TextView text = (TextView) convertView.findViewById(R.id.call_and_sms_text);
 
         View mainAction = convertView.findViewById(R.id.call_and_sms_main_action);
         mainAction.setOnClickListener(mPrimaryActionListener);
@@ -603,24 +606,12 @@
         }
         text.setText(entry.text);
 
-        View line2 = convertView.findViewById(R.id.call_and_sms_line2);
-        boolean numberEmpty = TextUtils.isEmpty(entry.number);
-        boolean labelEmpty = TextUtils.isEmpty(entry.label) || numberEmpty;
-        if (labelEmpty && numberEmpty) {
-            line2.setVisibility(View.GONE);
+        TextView label = (TextView) convertView.findViewById(R.id.call_and_sms_label);
+        if (TextUtils.isEmpty(entry.label)) {
+            label.setVisibility(View.GONE);
         } else {
-            line2.setVisibility(View.VISIBLE);
-
-            TextView label = (TextView) convertView.findViewById(R.id.call_and_sms_label);
-            if (labelEmpty) {
-                label.setVisibility(View.GONE);
-            } else {
-                label.setText(entry.label);
-                label.setVisibility(View.VISIBLE);
-            }
-
-            TextView number = (TextView) convertView.findViewById(R.id.call_and_sms_number);
-            number.setText(entry.number);
+            label.setText(entry.label);
+            label.setVisibility(View.VISIBLE);
         }
     }
 
diff --git a/src/com/android/contacts/ContactLoader.java b/src/com/android/contacts/ContactLoader.java
index 064deb5..ceaa246 100644
--- a/src/com/android/contacts/ContactLoader.java
+++ b/src/com/android/contacts/ContactLoader.java
@@ -113,7 +113,7 @@
         private final boolean mStarred;
         private final Integer mPresence;
         private final ArrayList<Entity> mEntities;
-        private ArrayList<StreamItemEntry> mStreamItems;
+        private final ArrayList<StreamItemEntry> mStreamItems;
         private final HashMap<Long, DataStatus> mStatuses;
         private final ArrayList<AccountType> mInvitableAccountTypes;
 
@@ -127,9 +127,9 @@
 
         private boolean mLoadingPhoto;
         private byte[] mPhotoBinaryData;
-        private boolean mSendToVoicemail;
-        private String mCustomRingtone;
-        private boolean mIsUserProfile;
+        private final boolean mSendToVoicemail;
+        private final String mCustomRingtone;
+        private final boolean mIsUserProfile;
 
         /**
          * Constructor for case "no contact found". This must only be used for the
@@ -618,7 +618,9 @@
                         loadStreamItems(result);
                     }
                     loadPhotoBinaryData(result);
-                    if (mLoadInvitableAccountTypes) {
+
+                    // Note ME profile should never have "Add connection"
+                    if (mLoadInvitableAccountTypes && !result.isUserProfile()) {
                         loadInvitableAccountTypes(result);
                     }
                 }
diff --git a/src/com/android/contacts/GroupListLoader.java b/src/com/android/contacts/GroupListLoader.java
index 39c428f..b567ba8 100644
--- a/src/com/android/contacts/GroupListLoader.java
+++ b/src/com/android/contacts/GroupListLoader.java
@@ -37,7 +37,6 @@
         Groups.ACTION,
         Groups.ACTION_URI,
         Groups.SUMMARY_COUNT,
-        Groups.SUMMARY_GROUP_COUNT_PER_ACCOUNT,
     };
 
     public final static int ACCOUNT_NAME = 0;
@@ -48,10 +47,8 @@
     public final static int ACTION = 5;
     public final static int ACTION_URI = 6;
     public final static int MEMBER_COUNT = 7;
-    public final static int GROUP_COUNT_PER_ACCOUNT = 8;
 
-    private static final Uri GROUP_LIST_URI = Groups.CONTENT_SUMMARY_URI.buildUpon()
-            .appendQueryParameter(Groups.PARAM_RETURN_GROUP_COUNT_PER_ACCOUNT, "true").build();
+    private static final Uri GROUP_LIST_URI = Groups.CONTENT_SUMMARY_URI;
 
     public GroupListLoader(Context context) {
         super(context, GROUP_LIST_URI, COLUMNS, Groups.ACCOUNT_TYPE + " NOT NULL AND "
diff --git a/src/com/android/contacts/activities/ActionBarAdapter.java b/src/com/android/contacts/activities/ActionBarAdapter.java
index 5a32d74..0c0841c 100644
--- a/src/com/android/contacts/activities/ActionBarAdapter.java
+++ b/src/com/android/contacts/activities/ActionBarAdapter.java
@@ -211,6 +211,10 @@
         return mSearchMode;
     }
 
+    public boolean shouldShowSearchResult() {
+        return mSearchMode && !TextUtils.isEmpty(mQueryString);
+    }
+
     public void setSearchMode(boolean flag) {
         if (mSearchMode != flag) {
             mSearchMode = flag;
diff --git a/src/com/android/contacts/activities/DialtactsActivity.java b/src/com/android/contacts/activities/DialtactsActivity.java
index 80bd5c1..13ce317 100644
--- a/src/com/android/contacts/activities/DialtactsActivity.java
+++ b/src/com/android/contacts/activities/DialtactsActivity.java
@@ -392,10 +392,14 @@
         if (fragment instanceof DialpadFragment) {
             mDialpadFragment = (DialpadFragment) fragment;
             mDialpadFragment.setListener(mDialpadListener);
-            mDialpadFragment.onVisibilityChanged(currentPosition == TAB_INDEX_DIALER);
+            if (currentPosition == TAB_INDEX_DIALER) {
+                mDialpadFragment.onVisibilityChanged(true);
+            }
         } else if (fragment instanceof CallLogFragment) {
             mCallLogFragment = (CallLogFragment) fragment;
-            mCallLogFragment.onVisibilityChanged(currentPosition == TAB_INDEX_CALL_LOG);
+            if (currentPosition == TAB_INDEX_CALL_LOG) {
+                mCallLogFragment.onVisibilityChanged(true);
+            }
         } else if (fragment instanceof ContactTileListFragment) {
             mStrequentFragment = (ContactTileListFragment) fragment;
             mStrequentFragment.enableQuickContact(false);
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index fc9879a..cab8afd 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -867,11 +867,11 @@
     }
 
     private void configureContactListFragment() {
-        final boolean searchMode = mActionBarAdapter.isSearchMode();
-        mAllFragment.setSearchMode(searchMode);
+        final boolean showSearchResult = mActionBarAdapter.shouldShowSearchResult();
+        mAllFragment.setSearchMode(showSearchResult);
 
         final boolean useTwoPane = PhoneCapabilityTester.isUsingTwoPanes(this);
-        mAllFragment.setVisibleScrollbarEnabled(!searchMode);
+        mAllFragment.setVisibleScrollbarEnabled(!showSearchResult);
         mAllFragment.setVerticalScrollbarPosition(
                 useTwoPane
                         ? View.SCROLLBAR_POSITION_LEFT
diff --git a/src/com/android/contacts/calllog/CallLogFragment.java b/src/com/android/contacts/calllog/CallLogFragment.java
index 0713e0e..2d0ddbd 100644
--- a/src/com/android/contacts/calllog/CallLogFragment.java
+++ b/src/com/android/contacts/calllog/CallLogFragment.java
@@ -24,6 +24,7 @@
 import com.android.contacts.R;
 import com.android.contacts.activities.DialtactsActivity;
 import com.android.contacts.activities.DialtactsActivity.ViewPagerVisibilityListener;
+import com.android.contacts.test.NeededForTesting;
 import com.android.contacts.util.ExpirableCache;
 import com.android.contacts.voicemail.VoicemailStatusHelper;
 import com.android.contacts.voicemail.VoicemailStatusHelper.StatusMessage;
@@ -167,6 +168,8 @@
     private boolean mScrollToTop;
 
     private boolean mShowOptionsMenu;
+    /** Whether we are currently filtering over voicemail. */
+    private boolean mShowingVoicemailOnly = false;
 
     private VoicemailStatusHelper mVoicemailStatusHelper;
     private View mStatusMessageView;
@@ -228,6 +231,10 @@
         public void addGroup(int cursorPosition, int size, boolean expanded);
     }
 
+    public interface CallFetcher {
+        public void fetchAllCalls();
+    }
+
     /** Adapter class to fill in data for the Call Log */
     public static final class CallLogAdapter extends GroupingListAdapter
             implements Runnable, ViewTreeObserver.OnPreDrawListener, GroupCreator {
@@ -236,7 +243,7 @@
 
         private final Context mContext;
         private final String mCurrentCountryIso;
-        private final CallLogQueryHandler mCallLogQueryHandler;
+        private final CallFetcher mCallFetcher;
 
         /**
          * A cache of the contact details for the phone numbers in the call log.
@@ -320,13 +327,13 @@
             }
         };
 
-        public CallLogAdapter(Context context, CallLogQueryHandler callLogQueryHandler,
+        public CallLogAdapter(Context context, CallFetcher callFetcher,
                 String currentCountryIso, String voicemailNumber) {
             super(context);
 
             mContext = context;
             mCurrentCountryIso = currentCountryIso;
-            mCallLogQueryHandler = callLogQueryHandler;
+            mCallFetcher = callFetcher;
 
             mContactInfoCache = ExpirableCache.create(CONTACT_INFO_CACHE_SIZE);
             mRequests = new LinkedList<String>();
@@ -350,9 +357,9 @@
          */
         @Override
         protected void onContentChanged() {
-            // Start async requery
-            setLoading(true);
-            mCallLogQueryHandler.fetchAllCalls();
+            // When the content changes, always fetch all the calls, in case a new missed call came
+            // in and we were filtering over voicemail only, so that we see the missed call.
+            mCallFetcher.fetchAllCalls();
         }
 
         void setLoading(boolean loading) {
@@ -694,7 +701,7 @@
             if (section == CallLogQuery.SECTION_NEW_HEADER
                     || section == CallLogQuery.SECTION_OLD_HEADER) {
                 views.listItemView.setVisibility(View.GONE);
-                views.listHeaderTextView.setVisibility(View.VISIBLE);
+                views.listHeaderView.setVisibility(View.VISIBLE);
                 views.listHeaderTextView.setText(
                         section == CallLogQuery.SECTION_NEW_HEADER
                                 ? R.string.call_log_new_header
@@ -704,7 +711,7 @@
             }
             // Default case: an item in the call log.
             views.listItemView.setVisibility(View.VISIBLE);
-            views.listHeaderTextView.setVisibility(View.GONE);
+            views.listHeaderView.setVisibility(View.GONE);
 
             final String number = c.getString(CallLogQuery.NUMBER);
             final long date = c.getLong(CallLogQuery.DATE);
@@ -921,8 +928,13 @@
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         String currentCountryIso = ContactsUtils.getCurrentCountryIso(getActivity());
-        mAdapter = new CallLogAdapter(getActivity(), mCallLogQueryHandler, currentCountryIso,
-                getVoiceMailNumber());
+        mAdapter = new CallLogAdapter(getActivity(),
+                new CallFetcher() {
+                    @Override
+                    public void fetchAllCalls() {
+                        startCallsQuery();
+                    }
+                }, currentCountryIso, mVoiceMailNumber);
         setListAdapter(mAdapter);
         getListView().setItemsCanFocus(true);
     }
@@ -978,7 +990,7 @@
     @Override
     public void onStop() {
         super.onStop();
-        resetNewCallsFlag();
+        updateOnExit();
     }
 
     @Override
@@ -988,13 +1000,13 @@
         mAdapter.changeCursor(null);
     }
 
-    private void resetNewCallsFlag() {
-        mCallLogQueryHandler.markNewCallsAsOld();
-    }
-
     private void startCallsQuery() {
         mAdapter.setLoading(true);
         mCallLogQueryHandler.fetchAllCalls();
+        if (mShowingVoicemailOnly) {
+            mShowingVoicemailOnly = false;
+            getActivity().invalidateOptionsMenu();
+        }
     }
 
     private void startVoicemailStatusQuery() {
@@ -1014,21 +1026,28 @@
         if (mShowOptionsMenu) {
             menu.findItem(R.id.menu_call_settings_call_log)
                 .setIntent(DialtactsActivity.getCallSettingsIntent());
+            menu.findItem(R.id.show_voicemails_only).setVisible(!mShowingVoicemailOnly);
+            menu.findItem(R.id.show_all_calls).setVisible(mShowingVoicemailOnly);
         }
     }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
-            case R.id.delete_all: {
+            case R.id.delete_all:
                 ClearCallLogDialog.show(getFragmentManager());
                 return true;
-            }
 
-            case R.id.show_voicemails_only: {
+            case R.id.show_voicemails_only:
                 mCallLogQueryHandler.fetchVoicemailOnly();
+                mShowingVoicemailOnly = true;
                 return true;
-            }
+
+            case R.id.show_all_calls:
+                mCallLogQueryHandler.fetchAllCalls();
+                mShowingVoicemailOnly = false;
+                return true;
+
             default:
                 return false;
         }
@@ -1114,12 +1133,12 @@
         }
     }
 
-    @VisibleForTesting
+    @NeededForTesting
     public CallLogAdapter getAdapter() {
         return mAdapter;
     }
 
-    @VisibleForTesting
+    @NeededForTesting
     public String getVoiceMailNumber() {
         return mVoiceMailNumber;
     }
@@ -1130,6 +1149,10 @@
         if (visible && isResumed()) {
             refreshData();
         }
+
+        if (!visible) {
+            updateOnExit();
+        }
     }
 
     /** Requests updates to the data to be shown. */
@@ -1140,11 +1163,7 @@
         startCallsQuery();
         startVoicemailStatusQuery();
         mAdapter.mPreDrawListener = null; // Let it restart the thread after next draw
-        // We don't want to remove notification when keyguard is on because the user has likely not
-        // seen the new call yet.
-        if (!mKeyguardManager.inKeyguardRestrictedInputMode()) {
-            removeMissedCallNotifications();
-        }
+        updateOnEntry();
     }
 
     /** Removes the missed call notifications. */
@@ -1162,4 +1181,36 @@
             Log.e(TAG, "Failed to clear missed calls notification due to remote exception");
         }
     }
+
+    /** Updates call data and notification state while leaving the call log tab. */
+    private void updateOnExit() {
+        updateOnTransition(false);
+    }
+
+    /** Updates call data and notification state while entering the call log tab. */
+    private void updateOnEntry() {
+        updateOnTransition(true);
+    }
+
+    private void updateOnTransition(boolean onEntry) {
+        // We don't want to update any call data when keyguard is on because the user has likely not
+        // seen the new calls yet.
+        if (!mKeyguardManager.inKeyguardRestrictedInputMode()) {
+            // On either of the transitions we reset the new flag and update the notifications.
+            // While exiting we additionally consume all missed calls (by marking them as read).
+            // This will ensure that they no more appear in the "new" section when we return back.
+            mCallLogQueryHandler.markNewCallsAsOld();
+            if (!onEntry) {
+                mCallLogQueryHandler.markMissedCallsAsRead();
+            }
+            removeMissedCallNotifications();
+            updateVoicemailNotifications();
+        }
+    }
+
+    private void updateVoicemailNotifications() {
+        Intent serviceIntent = new Intent(getActivity(), CallLogNotificationsService.class);
+        serviceIntent.setAction(CallLogNotificationsService.ACTION_UPDATE_NOTIFICATIONS);
+        getActivity().startService(serviceIntent);
+    }
 }
diff --git a/src/com/android/contacts/calllog/CallLogListItemViews.java b/src/com/android/contacts/calllog/CallLogListItemViews.java
index fbf91cc..847e354 100644
--- a/src/com/android/contacts/calllog/CallLogListItemViews.java
+++ b/src/com/android/contacts/calllog/CallLogListItemViews.java
@@ -43,13 +43,15 @@
     public final PhoneCallDetailsViews phoneCallDetailsViews;
     /** The item view for a stand-alone row, or null for other types of rows. */
     public final View listItemView;
-    /** The text of the header in a stand-alone row, or null for other types of rows. */
+    /** The header of a section. */
+    public final View listHeaderView;
+    /** The text of the header of a section. */
     public final TextView listHeaderTextView;
 
     private CallLogListItemViews(QuickContactBadge quickContactView, View primaryActionView,
             ImageView secondaryActionView, View unheardView, View dividerView,
             PhoneCallDetailsViews phoneCallDetailsViews, View listItemView,
-            TextView listHeaderTextView) {
+            View listHeaderView, TextView listHeaderTextView) {
         this.quickContactView = quickContactView;
         this.primaryActionView = primaryActionView;
         this.secondaryActionView = secondaryActionView;
@@ -57,6 +59,7 @@
         this.dividerView = dividerView;
         this.phoneCallDetailsViews = phoneCallDetailsViews;
         this.listItemView = listItemView;
+        this.listHeaderView = listHeaderView;
         this.listHeaderTextView = listHeaderTextView;
     }
 
@@ -69,6 +72,7 @@
                 view.findViewById(R.id.divider),
                 PhoneCallDetailsViews.fromView(view),
                 view.findViewById(R.id.call_log_item),
+                view.findViewById(R.id.call_log_header),
                 (TextView) view.findViewById(R.id.call_log_header_text));
     }
 
@@ -81,6 +85,7 @@
                 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 68ac63a..b4e4248 100644
--- a/src/com/android/contacts/calllog/CallLogQueryHandler.java
+++ b/src/com/android/contacts/calllog/CallLogQueryHandler.java
@@ -51,9 +51,12 @@
     private static final int QUERY_OLD_CALLS_TOKEN = 54;
     /** The token for the query to mark all missed calls as old after seeing the call log. */
     private static final int UPDATE_MARK_AS_OLD_TOKEN = 55;
+    /** The token for the query to mark all missed calls as read after seeing the call log. */
+    private static final int UPDATE_MARK_MISSED_CALL_AS_READ_TOKEN = 56;
 
     /** The token for the query to fetch voicemail status messages. */
-    private static final int QUERY_VOICEMAIL_STATUS_TOKEN = 56;
+    private static final int QUERY_VOICEMAIL_STATUS_TOKEN = 57;
+
 
     private final WeakReference<Listener> mListener;
 
@@ -149,14 +152,11 @@
 
     /** Fetches the list of calls in the call log, either the new one or the old ones. */
     private void fetchCalls(int token, boolean isNew, boolean voicemailOnly) {
-        // We need to check for NULL explicitly otherwise entries with where NEW or READ are NULL
+        // We need to check for NULL explicitly otherwise entries with where READ is NULL
         // may not match either the query or its negation.
-        String selection =
-                String.format(
-                        "(%s IS NOT NULL AND %s = 1 AND (%s = ? OR %s = ?)) OR " +
-                        "(%s IS NOT NULL AND %s = 0)",
-                        Calls.NEW, Calls.NEW, Calls.TYPE, Calls.TYPE, Calls.IS_READ, Calls.IS_READ);
-        final String[] selectionArgs;
+        // We consider the calls that are not yet consumed (i.e. IS_READ = 0) as "new".
+        String selection = String.format("%s IS NOT NULL AND %s = 0", Calls.IS_READ, Calls.IS_READ);
+        String[] selectionArgs = null;
         if (!isNew) {
             // Negate the query.
             selection = String.format("NOT (%s)", selection);
@@ -165,13 +165,6 @@
             // Add a clause to fetch only items of type voicemail.
             selection = String.format("(%s) AND (%s = ?)", selection, Calls.TYPE);
             selectionArgs = new String[]{
-                    Integer.toString(Calls.MISSED_TYPE),
-                    Integer.toString(Calls.VOICEMAIL_TYPE),
-                    Integer.toString(Calls.VOICEMAIL_TYPE),
-            };
-        } else {
-            selectionArgs = new String[]{
-                    Integer.toString(Calls.MISSED_TYPE),
                     Integer.toString(Calls.VOICEMAIL_TYPE),
             };
         }
@@ -199,6 +192,21 @@
                 values, where.toString(), null);
     }
 
+    /** Updates all missed calls to mark them as read. */
+    public void markMissedCallsAsRead() {
+        // Mark all "new" calls as not new anymore.
+        StringBuilder where = new StringBuilder();
+        where.append(Calls.IS_READ).append(" = 0");
+        where.append(" AND ");
+        where.append(Calls.TYPE).append(" = ").append(Calls.MISSED_TYPE);
+
+        ContentValues values = new ContentValues(1);
+        values.put(Calls.IS_READ, "1");
+
+        startUpdate(UPDATE_MARK_MISSED_CALL_AS_READ_TOKEN, null, Calls.CONTENT_URI, values,
+                where.toString(), null);
+    }
+
     /**
      * Invalidate the current list of calls.
      * <p>
diff --git a/src/com/android/contacts/calllog/IntentProvider.java b/src/com/android/contacts/calllog/IntentProvider.java
index 8173238..9ce3d3d 100644
--- a/src/com/android/contacts/calllog/IntentProvider.java
+++ b/src/com/android/contacts/calllog/IntentProvider.java
@@ -84,7 +84,15 @@
                     return null;
                 }
                 Intent intent = new Intent(context, CallDetailActivity.class);
-                if (adapter.isGroupHeader(position)) {
+                // Check if the first item is a voicemail.
+                String voicemailUri = cursor.getString(CallLogQuery.VOICEMAIL_URI);
+                if (voicemailUri != null) {
+                    intent.putExtra(CallDetailActivity.EXTRA_VOICEMAIL_URI,
+                            Uri.parse(voicemailUri));
+                }
+                intent.putExtra(CallDetailActivity.EXTRA_VOICEMAIL_START_PLAYBACK, false);
+
+                if (groupSize > 1) {
                     // We want to restore the position in the cursor at the end.
                     long[] ids = new long[groupSize];
                     // Copy the ids of the rows in the group.
@@ -97,12 +105,6 @@
                     // If there is a single item, use the direct URI for it.
                     intent.setData(ContentUris.withAppendedId(
                             Calls.CONTENT_URI_WITH_VOICEMAIL, id));
-                    String voicemailUri = cursor.getString(CallLogQuery.VOICEMAIL_URI);
-                    if (voicemailUri != null) {
-                        intent.putExtra(CallDetailActivity.EXTRA_VOICEMAIL_URI,
-                                Uri.parse(voicemailUri));
-                    }
-                    intent.putExtra(CallDetailActivity.EXTRA_VOICEMAIL_START_PLAYBACK, false);
                 }
                 return intent;
             }
diff --git a/src/com/android/contacts/detail/CarouselTab.java b/src/com/android/contacts/detail/CarouselTab.java
index 9b8efd5..26397ff 100644
--- a/src/com/android/contacts/detail/CarouselTab.java
+++ b/src/com/android/contacts/detail/CarouselTab.java
@@ -94,8 +94,6 @@
 
     @Override
     public void setAlphaLayerValue(float alpha) {
-        if (mAlphaLayer != null) {
-            mAlphaLayer.setAlpha(alpha);
-        }
+        ContactDetailDisplayUtils.setAlphaOnViewBackground(mAlphaLayer, alpha);
     }
 }
diff --git a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
index f74b56a..cbdf148 100644
--- a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
+++ b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
@@ -222,6 +222,8 @@
         if (!contactData.getStreamItems().isEmpty()) {
             StreamItemEntry firstEntry = contactData.getStreamItems().get(0);
             snippet = Html.fromHtml(firstEntry.getText());
+            // Add quotes around the text
+            snippet = context.getString(R.string.recent_updates_tab_text, snippet);
             if (!firstEntry.getPhotos().isEmpty()) {
                 StreamItemPhotoEntry firstPhoto = firstEntry.getPhotos().get(0);
                 photoUri = firstPhoto.getPhotoUri();
@@ -450,4 +452,15 @@
             }
         }
     }
+
+    /**
+     * Sets an alpha value on the view.
+     */
+    public static void setAlphaOnViewBackground(View view, float alpha) {
+        if (view != null) {
+            // Convert alpha layer to a black background HEX color with an alpha value for better
+            // performance (i.e. use setBackgroundColor() instead of setAlpha())
+            view.setBackgroundColor((int) (alpha * 255) << 24);
+        }
+    }
 }
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index 47617d3..bbf9d5b 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -142,7 +142,6 @@
     private NfcHandler mNfcHandler;
 
     private ContactLoader.Result mContactData;
-    private ViewGroup mHeaderView;
     private ImageView mStaticPhotoView;
     private ListView mListView;
     private ViewAdapter mAdapter;
@@ -316,9 +315,7 @@
 
     @Override
     public void setAlphaLayerValue(float alpha) {
-        if (mAlphaLayer != null) {
-            mAlphaLayer.setAlpha(alpha);
-        }
+        ContactDetailDisplayUtils.setAlphaOnViewBackground(mAlphaLayer, alpha);
     }
 
     @Override
@@ -396,9 +393,6 @@
             return;
         }
 
-        // Clear old header
-        mHeaderView = null;
-
         // Figure out if the contact has social updates or not
         mContactHasSocialUpdates = !mContactData.getStreamItems().isEmpty();
 
@@ -791,13 +785,16 @@
         String attribution = ContactDetailDisplayUtils.getAttribution(mContext, mContactData);
         boolean hasAttribution = !TextUtils.isEmpty(attribution);
         int networksCount = mOtherEntriesMap.keySet().size();
+
+        // Note: invitableCount will always be 0 for me profile.  (ContactLoader won't set
+        // invitable types for me profile.)
         int invitableCount = mContactData.getInvitableAccountTypes().size();
         if (!hasAttribution && networksCount == 0 && invitableCount == 0) {
             return;
         }
 
         // Add a title
-        String networkKindTitle = mContext.getString(R.string.network);
+        String networkKindTitle = mContext.getString(R.string.connections);
         mAllEntries.add(new KindTitleViewEntry(networkKindTitle.toUpperCase()));
 
         // Add the attribution if applicable
@@ -1149,7 +1146,7 @@
             // TODO Icon is temporary.  Need proper one.
             return new NetworkTitleViewEntry(
                     context.getResources().getDrawable(R.drawable.ic_menu_add_field_holo_light),
-                    context.getString(R.string.more_networks_button),
+                    context.getString(R.string.add_connection_button),
                     onClickListener);
         }
 
@@ -1340,6 +1337,25 @@
     }
 
     /**
+     * Cache of the children views for a view that displays a header view entry.
+     */
+    private static class HeaderViewCache {
+        public final TextView displayNameView;
+        public final TextView companyView;
+        public final ImageView photoView;
+        public final CheckBox starredView;
+        public final int layoutResourceId;
+
+        public HeaderViewCache(View view, int layoutResourceInflated) {
+            displayNameView = (TextView) view.findViewById(R.id.name);
+            companyView = (TextView) view.findViewById(R.id.company);
+            photoView = (ImageView) view.findViewById(R.id.photo);
+            starredView = (CheckBox) view.findViewById(R.id.star);
+            layoutResourceId = layoutResourceInflated;
+        }
+    }
+
+    /**
      * Cache of the children views for a view that displays a {@link NetworkTitleViewEntry}
      */
     private static class NetworkTitleViewCache {
@@ -1421,53 +1437,58 @@
         }
 
         private View getHeaderEntryView(View convertView, ViewGroup parent) {
-            // We don't want to rely on the recycled header view because it may
-            // have been left over from a previously viewed contact (since we
-            // reuse the adapter), so we would have to bind the data to the
-            // header each time. However, since there is only 1 header per list,
-            // just hold onto the original header view for this contact and
-            // return that each time.
-            if (mHeaderView != null) {
-                return mHeaderView;
-            }
-
-            int resourceId = mContactHasSocialUpdates ?
+            final int desiredLayoutResourceId = mContactHasSocialUpdates ?
                     R.layout.detail_header_contact_with_updates :
                     R.layout.detail_header_contact_without_updates;
-            mHeaderView = (ViewGroup) inflate(resourceId, parent, false);
+            View result = null;
+            HeaderViewCache viewCache = null;
 
-            TextView displayNameView = (TextView) mHeaderView.findViewById(R.id.name);
-            TextView companyView = (TextView) mHeaderView.findViewById(R.id.company);
-            ImageView photoView = (ImageView) mHeaderView.findViewById(R.id.photo);
+            // Only use convertView if it has the same layout resource ID as the one desired
+            // (the two can be different on wide 2-pane screens where the detail fragment is reused
+            // for many different contacts that do and do not have social updates).
+            if (convertView != null) {
+                viewCache = (HeaderViewCache) convertView.getTag();
+                if (viewCache.layoutResourceId == desiredLayoutResourceId) {
+                    result = convertView;
+                }
+            }
 
-            ContactDetailDisplayUtils.setDisplayName(mContext, mContactData, displayNameView);
-            ContactDetailDisplayUtils.setCompanyName(mContext, mContactData, companyView);
+            // Otherwise inflate a new header view and create a new view cache.
+            if (result == null) {
+                result = mInflater.inflate(desiredLayoutResourceId, parent, false);
+                viewCache = new HeaderViewCache(result, desiredLayoutResourceId);
+                result.setTag(viewCache);
+            }
+
+            ContactDetailDisplayUtils.setDisplayName(mContext, mContactData,
+                    viewCache.displayNameView);
+            ContactDetailDisplayUtils.setCompanyName(mContext, mContactData, viewCache.companyView);
 
             // Set the photo if it should be displayed
-            if (photoView != null) {
-                ContactDetailDisplayUtils.setPhoto(mContext, mContactData, photoView);
+            if (viewCache.photoView != null) {
+                ContactDetailDisplayUtils.setPhoto(mContext, mContactData, viewCache.photoView);
             }
 
             // Set the starred state if it should be displayed
-            final CheckBox starredView = (CheckBox) mHeaderView.findViewById(R.id.star);
-            if (starredView != null) {
-                ContactDetailDisplayUtils.setStarred(mContactData, starredView);
+            final CheckBox favoritesStar = viewCache.starredView;
+            if (favoritesStar != null) {
+                ContactDetailDisplayUtils.setStarred(mContactData, favoritesStar);
                 final Uri lookupUri = mContactData.getLookupUri();
-                starredView.setOnClickListener(new OnClickListener() {
+                favoritesStar.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         // Toggle "starred" state
                         // Make sure there is a contact
                         if (lookupUri != null) {
                             Intent intent = ContactSaveService.createSetStarredIntent(
-                                    getContext(), lookupUri, starredView.isChecked());
+                                    getContext(), lookupUri, favoritesStar.isChecked());
                             getContext().startService(intent);
                         }
                     }
                 });
             }
 
-            return mHeaderView;
+            return result;
         }
 
         private View getSeparatorEntryView(int position, View convertView, ViewGroup parent) {
diff --git a/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java b/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
index 561d44e..7efcc51 100644
--- a/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
+++ b/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
@@ -98,27 +98,16 @@
             mAllowedHorizontalScrollLength = (2 * fragmentWidth) - screenWidth;
             mLowerThreshold = (screenWidth - fragmentWidth) / 2;
             mUpperThreshold = mAllowedHorizontalScrollLength - mLowerThreshold;
-
-            // Snap to the current page now that the allowed horizontal scroll length has been
-            // computed.
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    if (isAttachedToWindow() && mAboutFragment != null &&
-                            mUpdatesFragment != null) {
-                        snapToEdge();
-                    }
-                }
-            });
         }
     }
 
     public void setCurrentPage(int pageIndex) {
         if (mCurrentPage != pageIndex) {
             mCurrentPage = pageIndex;
-            if (isAttachedToWindow() && mAboutFragment != null && mUpdatesFragment != null) {
-                snapToEdge();
-            }
+
+            // This method could have been called before the view has been measured, so snap to edge
+            // only after the view is ready.
+            postRunnableToSnapToEdge();
         }
     }
 
@@ -131,7 +120,26 @@
         mUpdatesFragment.enableAlphaLayer();
         mUpdatesFragment.setAlphaLayerValue(mCurrentPage == UPDATES_PAGE ? 0 : MAX_ALPHA);
 
-        snapToEdge();
+        // This method could have been called before the view has been measured, so snap to edge
+        // only after the view is ready.
+        postRunnableToSnapToEdge();
+    }
+
+    /**
+     * Snap to the currently selected page only once all the view setup and measurement has
+     * completed (i.e. we need to know the allowed horizontal scroll width in order to
+     * snap to the correct page).
+     */
+    private void postRunnableToSnapToEdge() {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                if (isAttachedToWindow() && mAboutFragment != null &&
+                        mUpdatesFragment != null) {
+                    snapToEdge();
+                }
+            }
+        });
     }
 
     public int getCurrentPage() {
diff --git a/src/com/android/contacts/detail/ContactDetailTabCarousel.java b/src/com/android/contacts/detail/ContactDetailTabCarousel.java
index cc4f0ff..5daca05 100644
--- a/src/com/android/contacts/detail/ContactDetailTabCarousel.java
+++ b/src/com/android/contacts/detail/ContactDetailTabCarousel.java
@@ -162,7 +162,7 @@
         mAboutTab.setAlphaLayerValue(mLastScrollPosition * MAX_ALPHA /
                 mAllowedHorizontalScrollLength);
         mUpdatesTab.setAlphaLayerValue(MAX_ALPHA - mLastScrollPosition * MAX_ALPHA /
-                mAllowedVerticalScrollLength);
+                mAllowedHorizontalScrollLength);
     }
 
     @Override
diff --git a/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java b/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
index bb2bdb4..b2a203b 100644
--- a/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
@@ -31,7 +31,6 @@
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.AbsListView.OnScrollListener;
-import android.widget.TextView;
 
 public class ContactDetailUpdatesFragment extends ListFragment
         implements FragmentKeyListener, ViewOverlay {
@@ -104,11 +103,6 @@
         View rootView = mInflater.inflate(R.layout.contact_detail_updates_fragment, container,
                 false);
 
-        TextView titleTextView = (TextView) rootView.findViewById(R.id.kind);
-        if (titleTextView != null) {
-            titleTextView.setText(getString(R.string.recent_updates).toUpperCase());
-        }
-
         mAlphaLayer = rootView.findViewById(R.id.alpha_overlay);
         mTouchInterceptLayer = rootView.findViewById(R.id.touch_intercept_overlay);
 
@@ -137,14 +131,18 @@
         }
         mLookupUri = lookupUri;
         mContactData = result;
-        mStreamItemAdapter.setStreamItems(mContactData.getStreamItems());
+
+        // If the adapter has been created already, then try to set stream items. Otherwise,
+        // wait for the adapter to get initialized, after which we will try to set the stream items
+        // again.
+        if (mStreamItemAdapter != null) {
+            mStreamItemAdapter.setStreamItems(mContactData.getStreamItems());
+        }
     }
 
     @Override
     public void setAlphaLayerValue(float alpha) {
-        if (mAlphaLayer != null) {
-            mAlphaLayer.setAlpha(alpha);
-        }
+        ContactDetailDisplayUtils.setAlphaOnViewBackground(mAlphaLayer, alpha);
     }
 
     @Override
diff --git a/src/com/android/contacts/detail/StreamItemAdapter.java b/src/com/android/contacts/detail/StreamItemAdapter.java
index 95880d7..09aa20b 100644
--- a/src/com/android/contacts/detail/StreamItemAdapter.java
+++ b/src/com/android/contacts/detail/StreamItemAdapter.java
@@ -32,8 +32,12 @@
  * List adapter for stream items of a given contact.
  */
 public class StreamItemAdapter extends BaseAdapter {
+    /** The header view, hidden under the tab carousel, if present. */
     private static final int ITEM_VIEW_TYPE_HEADER = 0;
-    private static final int ITEM_VIEW_TYPE_STREAM_ITEM = 1;
+    /** The title shown in the updates stream. */
+    private static final int ITEM_VIEW_TYPE_TITLE = 1;
+    /** The updates in the list. */
+    private static final int ITEM_VIEW_TYPE_STREAM_ITEM = 2;
 
     private final Context mContext;
     private final View.OnClickListener mListener;
@@ -50,20 +54,20 @@
 
     @Override
     public int getCount() {
-        return mStreamItems.size() + 1;
+        return mStreamItems.size() + 2;
     }
 
     @Override
     public Object getItem(int position) {
-        if (position == 0) {
+        if (position == 0 || position == 1) {
             return null;
         }
-        return mStreamItems.get(position - 1);
+        return mStreamItems.get(position - 2);
     }
 
     @Override
     public long getItemId(int position) {
-        if (position == 0) {
+        if (position == 0 || position == 1) {
             return -1;
         }
         return position - 1;
@@ -74,6 +78,9 @@
         if (position == 0) {
             return mInflater.inflate(R.layout.updates_header_contact, null);
         }
+        if (position == 1) {
+            return mInflater.inflate(R.layout.updates_title, null);
+        }
         StreamItemEntry streamItem = (StreamItemEntry) getItem(position);
         View view = ContactDetailDisplayUtils.createStreamItemView(
                 mInflater, mContext, streamItem, null);
@@ -94,6 +101,9 @@
         if (position == 0) {
             return ITEM_VIEW_TYPE_HEADER;
         }
+        if (position == 1) {
+            return ITEM_VIEW_TYPE_TITLE;
+        }
         return ITEM_VIEW_TYPE_STREAM_ITEM;
     }
 
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index afc3ab1..e1b4e9f 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -693,7 +693,7 @@
 
                     @Override
                     public void onRequest(int request) {
-                        if (request == EditorListener.FIELD_CHANGED) {
+                        if (request == EditorListener.FIELD_CHANGED && !isEditingUserProfile()) {
                             acquireAggregationSuggestions(rawContactEditor);
                         }
                     }
@@ -803,7 +803,13 @@
         // TODO: Find a better way to handle shortcuts, i.e. onKeyDown()?
         menu.findItem(R.id.menu_done).setVisible(false);
 
-        menu.findItem(R.id.menu_split).setVisible(mState != null && mState.size() > 1);
+        // Split only if more than one raw profile and not a user profile
+        menu.findItem(R.id.menu_split).setVisible(mState != null && mState.size() > 1 &&
+                !isEditingUserProfile());
+        // Cannot join a user profile
+        menu.findItem(R.id.menu_join).setVisible(!isEditingUserProfile());
+
+
         int size = menu.size();
         for (int i = 0; i < size; i++) {
             menu.getItem(i).setEnabled(mEnabled);
@@ -967,7 +973,7 @@
         setEnabled(false);
 
         Intent intent = ContactSaveService.createSaveContactIntent(getActivity(), mState,
-                SAVE_MODE_EXTRA_KEY, saveMode, mNewLocalProfile || mIsUserProfile,
+                SAVE_MODE_EXTRA_KEY, saveMode, isEditingUserProfile(),
                 getActivity().getClass(), ContactEditorActivity.ACTION_SAVE_COMPLETED);
         getActivity().startService(intent);
         return true;
@@ -987,7 +993,7 @@
                     .setIconAttribute(android.R.attr.alertDialogIcon)
                     .setTitle(R.string.cancel_confirmation_dialog_title)
                     .setMessage(R.string.cancel_confirmation_dialog_message)
-                    .setPositiveButton(R.string.discard,
+                    .setPositiveButton(android.R.string.ok,
                         new DialogInterface.OnClickListener() {
                             @Override
                             public void onClick(DialogInterface dialog, int whichButton) {
@@ -1143,6 +1149,10 @@
         return false;
     }
 
+    private boolean isEditingUserProfile() {
+        return mNewLocalProfile || mIsUserProfile;
+    }
+
     public static interface Listener {
         /**
          * Contact was not found, so somehow close this fragment. This is raised after a contact
@@ -1333,6 +1343,9 @@
 
         final RawContactEditorView rawContactView =
                 (RawContactEditorView)getRawContactEditorView(mAggregationSuggestionsRawContactId);
+        if (rawContactView == null) {
+            return; // Raw contact deleted?
+        }
         final View anchorView = rawContactView.findViewById(R.id.anchor_view);
         mAggregationSuggestionPopup = new ListPopupWindow(mContext, null);
         mAggregationSuggestionPopup.setAnchorView(anchorView);
diff --git a/src/com/android/contacts/group/GroupBrowseListAdapter.java b/src/com/android/contacts/group/GroupBrowseListAdapter.java
index 6571b99..c8c16e6 100644
--- a/src/com/android/contacts/group/GroupBrowseListAdapter.java
+++ b/src/com/android/contacts/group/GroupBrowseListAdapter.java
@@ -253,7 +253,6 @@
         long groupId = mCursor.getLong(GroupListLoader.GROUP_ID);
         String title = mCursor.getString(GroupListLoader.TITLE);
         int memberCount = mCursor.getInt(GroupListLoader.MEMBER_COUNT);
-        int groupCountForThisAccount = mCursor.getInt(GroupListLoader.GROUP_COUNT_PER_ACCOUNT);
 
         // 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
@@ -273,7 +272,7 @@
         }
 
         return new GroupListItem(accountName, accountType, dataSet, groupId, title,
-                isFirstGroupInAccount, memberCount, groupCountForThisAccount);
+                isFirstGroupInAccount, memberCount);
     }
 
     @Override
@@ -349,10 +348,6 @@
                 entry.getAccountType(), entry.getDataSet());
         viewCache.accountType.setText(accountType.getDisplayLabel(mContext).toString());
         viewCache.accountName.setText(entry.getAccountName());
-
-        int count = entry.getGroupCountForThisAccount();
-        viewCache.groupCountForAccount.setText(mContext.getResources().getQuantityString(
-                R.plurals.num_groups_in_account, count, count));
     }
 
     private static Uri getGroupUriFromId(long groupId) {
@@ -379,7 +374,6 @@
     public static class GroupListItemViewCache {
         public final TextView accountType;
         public final TextView accountName;
-        public final TextView groupCountForAccount;
         public final TextView groupTitle;
         public final TextView groupMemberCount;
         public final View accountHeader;
@@ -389,7 +383,6 @@
         public GroupListItemViewCache(View view) {
             accountType = (TextView) view.findViewById(R.id.account_type);
             accountName = (TextView) view.findViewById(R.id.account_name);
-            groupCountForAccount = (TextView) view.findViewById(R.id.group_count);
             groupTitle = (TextView) view.findViewById(R.id.label);
             groupMemberCount = (TextView) view.findViewById(R.id.count);
             accountHeader = view.findViewById(R.id.group_list_header);
diff --git a/src/com/android/contacts/group/GroupBrowseListFragment.java b/src/com/android/contacts/group/GroupBrowseListFragment.java
index 835400f..aca638e 100644
--- a/src/com/android/contacts/group/GroupBrowseListFragment.java
+++ b/src/com/android/contacts/group/GroupBrowseListFragment.java
@@ -152,8 +152,6 @@
     }
 
     private void configureVerticalScrollbar() {
-        mListView.setFastScrollEnabled(true);
-        mListView.setFastScrollAlwaysVisible(true);
         mListView.setVerticalScrollbarPosition(mVerticalScrollbarPosition);
         mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY);
         int leftPadding = 0;
@@ -259,7 +257,8 @@
     protected void requestSelectionToScreen() {
         int selectedPosition = mAdapter.getSelectedGroupPosition();
         if (selectedPosition != -1) {
-            mListView.requestPositionToScreen(selectedPosition, true /* smooth scroll requested */);
+            mListView.requestPositionToScreen(selectedPosition,
+                    true /* smooth scroll requested */);
         }
     }
 
diff --git a/src/com/android/contacts/group/GroupEditorFragment.java b/src/com/android/contacts/group/GroupEditorFragment.java
index b060541..4712871 100644
--- a/src/com/android/contacts/group/GroupEditorFragment.java
+++ b/src/com/android/contacts/group/GroupEditorFragment.java
@@ -191,9 +191,9 @@
     private ContentResolver mContentResolver;
     private SuggestedMemberListAdapter mAutoCompleteAdapter;
 
-    private final List<Member> mListMembersToAdd = new ArrayList<Member>();
-    private final List<Member> mListMembersToRemove = new ArrayList<Member>();
-    private final List<Member> mListToDisplay = new ArrayList<Member>();
+    private ArrayList<Member> mListMembersToAdd = new ArrayList<Member>();
+    private ArrayList<Member> mListMembersToRemove = new ArrayList<Member>();
+    private ArrayList<Member> mListToDisplay = new ArrayList<Member>();
 
     public GroupEditorFragment() {
     }
@@ -273,9 +273,9 @@
         outState.putBoolean(KEY_GROUP_NAME_IS_READ_ONLY, mGroupNameIsReadOnly);
         outState.putString(KEY_ORIGINAL_GROUP_NAME, mOriginalGroupName);
 
-        outState.putParcelableArray(KEY_MEMBERS_TO_ADD, Member.toArray(mListMembersToAdd));
-        outState.putParcelableArray(KEY_MEMBERS_TO_REMOVE, Member.toArray(mListMembersToRemove));
-        outState.putParcelableArray(KEY_MEMBERS_TO_DISPLAY, Member.toArray(mListToDisplay));
+        outState.putParcelableArrayList(KEY_MEMBERS_TO_ADD, mListMembersToAdd);
+        outState.putParcelableArrayList(KEY_MEMBERS_TO_REMOVE, mListMembersToRemove);
+        outState.putParcelableArrayList(KEY_MEMBERS_TO_DISPLAY, mListToDisplay);
     }
 
     private void onRestoreInstanceState(Bundle state) {
@@ -291,10 +291,9 @@
         mGroupNameIsReadOnly = state.getBoolean(KEY_GROUP_NAME_IS_READ_ONLY);
         mOriginalGroupName = state.getString(KEY_ORIGINAL_GROUP_NAME);
 
-        Member.toList((Member[]) state.getParcelableArray(KEY_MEMBERS_TO_ADD), mListMembersToAdd);
-        Member.toList((Member[]) state.getParcelableArray(KEY_MEMBERS_TO_REMOVE),
-                mListMembersToRemove);
-        Member.toList((Member[]) state.getParcelableArray(KEY_MEMBERS_TO_DISPLAY), mListToDisplay);
+        mListMembersToAdd = state.getParcelableArrayList(KEY_MEMBERS_TO_ADD);
+        mListMembersToRemove = state.getParcelableArrayList(KEY_MEMBERS_TO_REMOVE);
+        mListToDisplay = state.getParcelableArrayList(KEY_MEMBERS_TO_DISPLAY);
     }
 
     public void setContentResolver(ContentResolver resolver) {
@@ -404,7 +403,10 @@
             mAutoCompleteTextView.setOnItemClickListener(new OnItemClickListener() {
                 @Override
                 public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-                    SuggestedMember member = mAutoCompleteAdapter.getItem(position);
+                    SuggestedMember member = (SuggestedMember) view.getTag();
+                    if (member == null) {
+                        return; // just in case
+                    }
                     loadMemberToAddToGroup(member.getRawContactId(),
                             String.valueOf(member.getContactId()));
 
@@ -515,7 +517,7 @@
                     .setIconAttribute(android.R.attr.alertDialogIcon)
                     .setTitle(R.string.cancel_confirmation_dialog_title)
                     .setMessage(R.string.cancel_confirmation_dialog_message)
-                    .setPositiveButton(R.string.discard,
+                    .setPositiveButton(android.R.string.ok,
                         new DialogInterface.OnClickListener() {
                             @Override
                             public void onClick(DialogInterface dialog, int whichButton) {
@@ -892,22 +894,6 @@
                 return new Member[size];
             }
         };
-
-        /** Convert to an array */
-        public static Member[] toArray(List<Member> list) {
-            return list.toArray(EMPTY_ARRAY);
-        }
-
-        /**
-         * Convert to a list.  Instead of creating a new one, this method clears the passed list
-         * and adds elements to it.
-         */
-        public static void toList(Member[] array, List<Member> list) {
-            list.clear();
-            for (Member member : array) {
-                list.add(member);
-            }
-        }
     }
 
     /**
diff --git a/src/com/android/contacts/group/GroupListItem.java b/src/com/android/contacts/group/GroupListItem.java
index c707ea7..a06ec38 100644
--- a/src/com/android/contacts/group/GroupListItem.java
+++ b/src/com/android/contacts/group/GroupListItem.java
@@ -28,12 +28,8 @@
     private final boolean mIsFirstGroupInAccount;
     private final int mMemberCount;
 
-    /** Number of groups in the account that this group belongs to */
-    private final int mGroupCountForThisAccount;
-
     public GroupListItem(String accountName, String accountType, String dataSet, long groupId,
-            String title, boolean isFirstGroupInAccount, int memberCount,
-            int groupCountForThisAccount) {
+            String title, boolean isFirstGroupInAccount, int memberCount) {
         mAccountName = accountName;
         mAccountType = accountType;
         mDataSet = dataSet;
@@ -41,7 +37,6 @@
         mTitle = title;
         mIsFirstGroupInAccount = isFirstGroupInAccount;
         mMemberCount = memberCount;
-        mGroupCountForThisAccount = groupCountForThisAccount;
     }
 
     public String getAccountName() {
@@ -75,8 +70,4 @@
     public boolean isFirstGroupInAccount() {
         return mIsFirstGroupInAccount;
     }
-
-    public int getGroupCountForThisAccount() {
-        return mGroupCountForThisAccount;
-    }
 }
\ No newline at end of file
diff --git a/src/com/android/contacts/group/SuggestedMemberListAdapter.java b/src/com/android/contacts/group/SuggestedMemberListAdapter.java
index f671b65..bc8055a 100644
--- a/src/com/android/contacts/group/SuggestedMemberListAdapter.java
+++ b/src/com/android/contacts/group/SuggestedMemberListAdapter.java
@@ -144,11 +144,11 @@
         byte[] byteArray = member.getPhotoByteArray();
         if (byteArray == null) {
             icon.setImageResource(R.drawable.ic_contact_picture);
-        }
-        else {
+        } else {
             Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
             icon.setImageBitmap(bitmap);
         }
+        result.setTag(member);
         return result;
     }
 
diff --git a/src/com/android/contacts/interactions/GroupDeletionDialogFragment.java b/src/com/android/contacts/interactions/GroupDeletionDialogFragment.java
index c9c1342..c1f3bd7 100644
--- a/src/com/android/contacts/interactions/GroupDeletionDialogFragment.java
+++ b/src/com/android/contacts/interactions/GroupDeletionDialogFragment.java
@@ -32,19 +32,15 @@
 
     private static final String ARG_GROUP_ID = "groupId";
     private static final String ARG_LABEL = "label";
-
-    private boolean mEndActivity;
-
-    public GroupDeletionDialogFragment(boolean endActivity) {
-        mEndActivity = endActivity;
-    }
+    private static final String ARG_SHOULD_END_ACTIVITY = "endActivity";
 
     public static void show(FragmentManager fragmentManager, long groupId, String label,
             boolean endActivity) {
-        GroupDeletionDialogFragment dialog = new GroupDeletionDialogFragment(endActivity);
+        GroupDeletionDialogFragment dialog = new GroupDeletionDialogFragment();
         Bundle args = new Bundle();
         args.putLong(ARG_GROUP_ID, groupId);
         args.putString(ARG_LABEL, label);
+        args.putBoolean(ARG_SHOULD_END_ACTIVITY, endActivity);
         dialog.setArguments(args);
         dialog.show(fragmentManager, "deleteGroup");
     }
@@ -76,8 +72,12 @@
 
         getActivity().startService(ContactSaveService.createGroupDeletionIntent(
                 getActivity(), groupId));
-        if (mEndActivity) {
+        if (shouldEndActivity()) {
             getActivity().finish();
         }
     }
+
+    private boolean shouldEndActivity() {
+        return getArguments().getBoolean(ARG_SHOULD_END_ACTIVITY);
+    }
 }
diff --git a/src/com/android/contacts/list/AccountFilterActivity.java b/src/com/android/contacts/list/AccountFilterActivity.java
index 9d872da..fb0cf9e 100644
--- a/src/com/android/contacts/list/AccountFilterActivity.java
+++ b/src/com/android/contacts/list/AccountFilterActivity.java
@@ -83,17 +83,17 @@
             accountFilters.add(ContactListFilter.createAccountFilter(account.type, account.name,
                     account.dataSet, icon, account.name));
         }
-        int count = accountFilters.size();
+        final int count = accountFilters.size();
 
         if (count >= 1) {
-            // If we only have one account, don't show it as "account", instead show it as "all"
             mFilters.add(ContactListFilter.createFilterWithType(
                     ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS));
+            // If we only have one account, don't show it as "account", instead show it as "all"
             if (count > 1) {
                 mFilters.addAll(accountFilters);
-                mFilters.add(ContactListFilter.createFilterWithType(
-                    ContactListFilter.FILTER_TYPE_CUSTOM));
             }
+            mFilters.add(ContactListFilter.createFilterWithType(
+                    ContactListFilter.FILTER_TYPE_CUSTOM));
         }
 
         mListView.setAdapter(new FilterListAdapter(this));
diff --git a/src/com/android/contacts/list/ContactEntryListAdapter.java b/src/com/android/contacts/list/ContactEntryListAdapter.java
index 4ac54dc..ba16c17 100644
--- a/src/com/android/contacts/list/ContactEntryListAdapter.java
+++ b/src/com/android/contacts/list/ContactEntryListAdapter.java
@@ -106,6 +106,7 @@
         ((ContactListPinnedHeaderView)pinnedHeaderView).setSectionHeader(title);
     }
 
+    @Override
     protected void setPinnedHeaderContactsCount(View header) {
         // Update the header with the contacts count only if a profile header exists
         // otherwise, the contacts count are shown in the empty profile header view
@@ -116,6 +117,7 @@
         }
     }
 
+    @Override
     protected void clearPinnedHeaderContactsCount(View header) {
         ((ContactListPinnedHeaderView)header).setCountView(null);
     }
@@ -455,10 +457,6 @@
         if (!mEmptyListEnabled) {
             return false;
         } else if (isSearchMode()) {
-            // TODO Do we really need this?  DefaultContactListAdapter overrides it and always
-            // return false, as it returns all contacts if in the search mode and the query is
-            // empty.  If there's no places relying on this behavior, we can just return false
-            // here.
             return TextUtils.isEmpty(getQueryString());
         } else if (mLoading) {
             // We don't want the empty state to show when loading.
diff --git a/src/com/android/contacts/list/ContactListItemView.java b/src/com/android/contacts/list/ContactListItemView.java
index 7ddece6..4c4b780 100644
--- a/src/com/android/contacts/list/ContactListItemView.java
+++ b/src/com/android/contacts/list/ContactListItemView.java
@@ -32,7 +32,6 @@
 import android.graphics.Rect;
 import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
-import android.provider.ContactsContract.Contacts;
 import android.text.TextUtils;
 import android.text.TextUtils.TruncateAt;
 import android.util.AttributeSet;
@@ -89,7 +88,6 @@
     private final int mCountViewTextSize;
     private final int mContactsCountTextColor;
     private final int mTextIndent;
-
     private Drawable mActivatedBackgroundDrawable;
 
     // Horizontal divider between contact views.
@@ -230,7 +228,7 @@
                 R.styleable.ContactListItemView_list_item_header_text_indent, 0);
         mHeaderTextColor = a.getColor(
                 R.styleable.ContactListItemView_list_item_header_text_color, Color.BLACK);
-        mHeaderTextSize = (int)a.getDimensionPixelSize(
+        mHeaderTextSize = a.getDimensionPixelSize(
                 R.styleable.ContactListItemView_list_item_header_text_size, 12);
         mHeaderBackgroundHeight = a.getDimensionPixelSize(
                 R.styleable.ContactListItemView_list_item_header_height, 30);
@@ -240,7 +238,7 @@
                 R.styleable.ContactListItemView_list_item_header_underline_color, 0);
         mTextIndent = a.getDimensionPixelOffset(
                 R.styleable.ContactListItemView_list_item_text_indent, 0);
-        mCountViewTextSize = (int)a.getDimensionPixelSize(
+        mCountViewTextSize = a.getDimensionPixelSize(
                 R.styleable.ContactListItemView_list_item_contacts_count_text_size, 12);
         mContactsCountTextColor = a.getColor(
                 R.styleable.ContactListItemView_list_item_contacts_count_text_color, Color.BLACK);
diff --git a/src/com/android/contacts/list/ContactListPinnedHeaderView.java b/src/com/android/contacts/list/ContactListPinnedHeaderView.java
index 5983007..5e95e4d 100644
--- a/src/com/android/contacts/list/ContactListPinnedHeaderView.java
+++ b/src/com/android/contacts/list/ContactListPinnedHeaderView.java
@@ -20,10 +20,8 @@
 
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.TypedValue;
@@ -124,7 +122,7 @@
         if (isViewMeasurable(mCountTextView)) {
             mCountTextView.layout(width - mPaddingRight - mCountTextView.getMeasuredWidth(),
                     0,
-                    width,
+                    width - mPaddingRight,
                     mHeaderBackgroundHeight);
         }
 
diff --git a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
index 4db2270..ca07516 100644
--- a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
@@ -41,11 +41,14 @@
     private View mSearchHeaderView;
     private TextView mAccountFilterHeaderView;
     private View mAccountFilterHeaderContainer;
+    private FrameLayout mProfileHeaderContainer;
     private View mProfileHeader;
     private Button mProfileMessage;
     private FrameLayout mMessageContainer;
     private View mProfileTitle;
 
+    private View mPaddingView;
+
     public DefaultContactBrowseListFragment() {
         setPhotoLoaderEnabled(true);
         setSectionHeaderDisplayEnabled(true);
@@ -137,11 +140,12 @@
         if (!isSearchMode() && data != null) {
             int count = data.getCount();
             if (count != 0) {
+                count -= (mUserProfileExists ? 1: 0);
                 String format = getResources().getQuantityText(
                         R.plurals.listTotalAllContacts, count).toString();
                 // Do not count the user profile in the contacts count
                 if (mUserProfileExists) {
-                    getAdapter().setContactsCount(String.format(format, count - 1));
+                    getAdapter().setContactsCount(String.format(format, count));
                 } else {
                     mCounterHeaderView.setText(String.format(format, count));
                 }
@@ -209,11 +213,14 @@
         // Changing visibility of just the mProfileHeader doesn't do anything unless
         // you change visibility of its children, hence the call to mCounterHeaderView
         // and mProfileTitle
+        mProfileHeaderContainer.setVisibility(show ? View.VISIBLE : View.GONE);
         mProfileHeader.setVisibility(show ? View.VISIBLE : View.GONE);
         mCounterHeaderView.setVisibility(show ? View.VISIBLE : View.GONE);
         mProfileTitle.setVisibility(show ? View.VISIBLE : View.GONE);
         mMessageContainer.setVisibility(show ? View.VISIBLE : View.GONE);
         mProfileMessage.setVisibility(show ? View.VISIBLE : View.GONE);
+
+        mPaddingView.setVisibility(show ? View.GONE : View.VISIBLE);
     }
 
     /**
@@ -226,14 +233,16 @@
 
         ListView list = getListView();
         // Put a header with the "ME" name and a view for the number of contacts
+        // The view is embedded in a frame view since you cannot change the visibility of a
+        // view in a ListView without having a parent view.
+        mProfileHeaderContainer = new FrameLayout(inflater.getContext());
         mProfileHeader = inflater.inflate(R.layout.user_profile_header, null, false);
         mCounterHeaderView = (TextView) mProfileHeader.findViewById(R.id.contacts_count);
         mProfileTitle = mProfileHeader.findViewById(R.id.profile_title);
-        list.addHeaderView(mProfileHeader, null, false);
+        mProfileHeaderContainer.addView(mProfileHeader);
+        list.addHeaderView(mProfileHeaderContainer, null, false);
 
         // Add a selectable view with a message inviting the user to create a local profile
-        // The view is embedded in a frame view since you cannot change the visibility of a
-        // view in a ListView without having a parent view.
         mMessageContainer = new FrameLayout(inflater.getContext());
         mProfileMessage = (Button)inflater.inflate(R.layout.user_profile_button, null, false);
         mMessageContainer.addView(mProfileMessage);
@@ -246,5 +255,11 @@
                 startActivity(intent);
             }
         });
+
+        View paddingViewContainer =
+                inflater.inflate(R.layout.contact_detail_list_padding, null, false);
+        mPaddingView = paddingViewContainer.findViewById(R.id.contact_detail_list_padding);
+        mPaddingView.setVisibility(View.GONE);
+        getListView().addHeaderView(paddingViewContainer);
     }
 }
diff --git a/src/com/android/contacts/list/DefaultContactListAdapter.java b/src/com/android/contacts/list/DefaultContactListAdapter.java
index f081921..bb49027 100644
--- a/src/com/android/contacts/list/DefaultContactListAdapter.java
+++ b/src/com/android/contacts/list/DefaultContactListAdapter.java
@@ -66,15 +66,11 @@
             }
             query = query.trim();
             if (TextUtils.isEmpty(query)) {
-                // Special case: if the query string is empty, show all contacts, regardless of the
-                // current filter.
-                // (We can't use the FILTER_URI for this, as the contacts provider would return
-                // an empty cursor if the query is empty.)
-                final ContactListFilter allFilter = ContactListFilter.createFilterWithType(
-                        ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS);
-                configureUri(loader, directoryId, allFilter);
-                configureProjection(loader, directoryId, allFilter);
-                configureSelection(loader, directoryId, allFilter);
+                // Regardless of the directory, we don't want anything returned,
+                // so let's just send a "nothing" query to the local directory.
+                loader.setUri(Contacts.CONTENT_URI);
+                loader.setProjection(PROJECTION_CONTACT);
+                loader.setSelection("0");
             } else {
                 Builder builder = Contacts.CONTENT_FILTER_URI.buildUpon();
                 builder.appendPath(query);      // Builder will encode the query
@@ -196,16 +192,16 @@
                                 + "SELECT DISTINCT " + RawContacts.CONTACT_ID
                                 + " FROM raw_contacts"
                                 + " WHERE " + RawContacts.ACCOUNT_TYPE + "=?"
-                                + " AND " + RawContacts.ACCOUNT_NAME + "=?"
-                                + " OR " + Contacts.IS_USER_PROFILE + "=1");
+                                + " AND " + RawContacts.ACCOUNT_NAME + "=?");
                 selectionArgs.add(filter.accountType);
                 selectionArgs.add(filter.accountName);
                 if (filter.dataSet != null) {
-                    selection.append(" AND " + RawContacts.DATA_SET + "=?)");
+                    selection.append(" AND " + RawContacts.DATA_SET + "=?");
                     selectionArgs.add(filter.dataSet);
                 } else {
-                    selection.append(" AND " + RawContacts.DATA_SET + " IS NULL)");
+                    selection.append(" AND " + RawContacts.DATA_SET + " IS NULL");
                 }
+                selection.append(" OR " + Contacts.IS_USER_PROFILE + "=1)");
                 break;
             }
             case ContactListFilter.FILTER_TYPE_GROUP: {
@@ -256,16 +252,4 @@
         return prefs.getBoolean(ContactsPreferences.PREF_DISPLAY_ONLY_PHONES,
                 ContactsPreferences.PREF_DISPLAY_ONLY_PHONES_DEFAULT);
     }
-
-    @Override
-    public boolean isEmpty() {
-        // ContactEntryListAdapter.isEmpty() returns false when in the search mode && the query is
-        // empty.  Here, we want to return all contacts in this case, override it and make it
-        // always return false.  See the TODO there -- we may not need this method entirely.
-        if (isSearchMode()) {
-            return false;
-        } else {
-            return super.isEmpty();
-        }
-    }
 }
diff --git a/src/com/android/contacts/list/PhoneNumberPickerFragment.java b/src/com/android/contacts/list/PhoneNumberPickerFragment.java
index 306efbd..5986b9c 100644
--- a/src/com/android/contacts/list/PhoneNumberPickerFragment.java
+++ b/src/com/android/contacts/list/PhoneNumberPickerFragment.java
@@ -48,6 +48,11 @@
 
     private TextView mAccountFilterHeaderView;
     private View mAccountFilterHeaderContainer;
+    /**
+     * Lives as ListView's header and is shown when {@link #mAccountFilterHeaderContainer} is set
+     * to View.GONE.
+     */
+    private View mPaddingView;
 
     private static final String KEY_FILTER = "filter";
 
@@ -80,6 +85,10 @@
     protected void onCreateView(LayoutInflater inflater, ViewGroup container) {
         super.onCreateView(inflater, container);
 
+        View paddingView = inflater.inflate(R.layout.contact_detail_list_padding, null, false);
+        mPaddingView = paddingView.findViewById(R.id.contact_detail_list_padding);
+        getListView().addHeaderView(paddingView);
+
         mAccountFilterHeaderView = (TextView) getView().findViewById(R.id.account_filter_header);
         mAccountFilterHeaderContainer =
                 getView().findViewById(R.id.account_filter_header_container);
@@ -101,8 +110,10 @@
                 mAccountFilterHeaderContainer.setVisibility(View.VISIBLE);
                 mAccountFilterHeaderView.setText(getContext().getString(
                         R.string.listAllContactsInAccount, filter.accountName));
+                mPaddingView.setVisibility(View.GONE);
             } else {
                 mAccountFilterHeaderContainer.setVisibility(View.GONE);
+                mPaddingView.setVisibility(View.VISIBLE);
             }
         }
     }
diff --git a/src/com/android/contacts/socialwidget/SocialWidgetProvider.java b/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
index ee41332..98a843e 100644
--- a/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
+++ b/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
@@ -137,7 +137,6 @@
             setDisplayNameAndSnippet(context, views,
                     context.getString(R.string.invalidContactMessage), null, null, null);
             setPhoto(views, ContactBadgeUtil.loadPlaceholderPhoto(context));
-            setStatusAttribution(views, null);
         } else {
             byte[] photo = contactData.getPhotoBinaryData();
             setPhoto(views, photo != null
@@ -145,11 +144,6 @@
                             : ContactBadgeUtil.loadPlaceholderPhoto(context));
 
             // TODO: Rotate between all the stream items?
-            StreamItemEntry streamItem = null;
-            if (!contactData.getStreamItems().isEmpty()) {
-                streamItem = contactData.getStreamItems().get(0);
-                setStatusAttribution(views, ContactBadgeUtil.getSocialDate(streamItem, context));
-            }
 
             // OnClick launch QuickContact
             final Intent intent = new Intent(QuickContact.ACTION_QUICK_CONTACT);
@@ -229,17 +223,4 @@
             }
         }
     }
-
-    /**
-     * Set the status attribution text to display in the header.
-     */
-    private static void setStatusAttribution(RemoteViews views,
-            CharSequence attribution) {
-        if (attribution == null) {
-            views.setViewVisibility(R.id.status_date, View.GONE);
-        } else {
-            views.setTextViewText(R.id.status_date, attribution);
-            views.setViewVisibility(R.id.status_date, View.VISIBLE);
-        }
-    }
 }
diff --git a/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java b/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
index 0b30cd9..5e53b76 100644
--- a/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
+++ b/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
@@ -19,17 +19,24 @@
 import static com.android.contacts.CallDetailActivity.EXTRA_VOICEMAIL_START_PLAYBACK;
 import static com.android.contacts.CallDetailActivity.EXTRA_VOICEMAIL_URI;
 
+import com.android.common.io.MoreCloseables;
 import com.android.contacts.R;
 import com.android.contacts.util.BackgroundTaskService;
 import com.android.ex.variablespeed.MediaPlayerProxy;
 import com.android.ex.variablespeed.VariableSpeed;
 import com.google.common.base.Preconditions;
 
+import android.app.Activity;
 import android.app.Fragment;
+import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.database.Cursor;
 import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Bundle;
+import android.provider.VoicemailContract;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -60,30 +67,19 @@
 public class VoicemailPlaybackFragment extends Fragment {
     private static final String TAG = "VoicemailPlayback";
     private static final int NUMBER_OF_THREADS_IN_POOL = 2;
+    private static final String[] HAS_CONTENT_PROJECTION = new String[] {
+        VoicemailContract.Voicemails.HAS_CONTENT,
+    };
 
     private VoicemailPlaybackPresenter mPresenter;
     private ScheduledExecutorService mScheduledExecutorService;
-    private SeekBar mPlaybackSeek;
-    private ImageButton mStartStopButton;
-    private ImageButton mPlaybackSpeakerphone;
-    private ImageButton mRateDecreaseButton;
-    private ImageButton mRateIncreaseButton;
-    private TextViewWithMessagesController mTextController;
+    private View mPlaybackLayout;
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
-        View view = inflater.inflate(R.layout.playback_layout, null);
-        mPlaybackSeek = (SeekBar) view.findViewById(R.id.playback_seek);
-        mPlaybackSeek = (SeekBar) view.findViewById(R.id.playback_seek);
-        mStartStopButton = (ImageButton) view.findViewById(R.id.playback_start_stop);
-        mPlaybackSpeakerphone = (ImageButton) view.findViewById(R.id.playback_speakerphone);
-        mRateDecreaseButton = (ImageButton) view.findViewById(R.id.rate_decrease_button);
-        mRateIncreaseButton = (ImageButton) view.findViewById(R.id.rate_increase_button);
-        mTextController = new TextViewWithMessagesController(
-                (TextView) view.findViewById(R.id.playback_position_text),
-                (TextView) view.findViewById(R.id.playback_speed_text));
-        return view;
+        mPlaybackLayout = inflater.inflate(R.layout.playback_layout, null);
+        return mPlaybackLayout;
     }
 
     @Override
@@ -95,7 +91,7 @@
         Uri voicemailUri = arguments.getParcelable(EXTRA_VOICEMAIL_URI);
         Preconditions.checkNotNull(voicemailUri, "fragment must contain EXTRA_VOICEMAIL_URI");
         boolean startPlayback = arguments.getBoolean(EXTRA_VOICEMAIL_START_PLAYBACK, false);
-        mPresenter = new VoicemailPlaybackPresenter(new PlaybackViewImpl(),
+        mPresenter = new VoicemailPlaybackPresenter(createPlaybackViewImpl(),
                 createMediaPlayer(mScheduledExecutorService), voicemailUri,
                 mScheduledExecutorService, startPlayback, getBackgroundTaskService());
         mPresenter.onCreate(savedInstanceState);
@@ -119,6 +115,11 @@
         super.onDestroy();
     }
 
+    private PlaybackViewImpl createPlaybackViewImpl() {
+        return new PlaybackViewImpl(new ActivityReference(), getActivity().getApplicationContext(),
+                mPlaybackLayout);
+    }
+
     private MediaPlayerProxy createMediaPlayer(ExecutorService executorService) {
         return VariableSpeed.createVariableSpeed(executorService);
     }
@@ -133,7 +134,7 @@
      * We always use four digits, two for minutes two for seconds.  In the very unlikely event
      * that the voicemail duration exceeds 99 minutes, the display is capped at 99 minutes.
      */
-    private String formatAsMinutesAndSeconds(int millis) {
+    private static String formatAsMinutesAndSeconds(int millis) {
         int seconds = millis / 1000;
         int minutes = seconds / 60;
         seconds -= minutes * 60;
@@ -143,25 +144,79 @@
         return String.format("%02d:%02d", minutes, seconds);
     }
 
-    private AudioManager getAudioManager() {
-        return (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
+    /**
+     * An object that can provide us with an Activity.
+     * <p>
+     * Fragments suffer the drawback that the Activity they belong to may sometimes be null. This
+     * can happen if the Fragment is detached, for example. In that situation a call to
+     * {@link Fragment#getString(int)} will throw and {@link IllegalStateException}. Also, calling
+     * {@link Fragment#getActivity()} is dangerous - it may sometimes return null. And thus blindly
+     * calling a method on the result of getActivity() is dangerous too.
+     * <p>
+     * To work around this, I have made the {@link PlaybackViewImpl} class static, so that it does
+     * not have access to any Fragment methods directly. Instead it uses an application Context for
+     * things like accessing strings, accessing system services. It only uses the Activity when it
+     * absolutely needs it - and does so through this class. This makes it easy to see where we have
+     * to check for null properly.
+     */
+    private final class ActivityReference {
+        /** Gets this Fragment's Activity: <b>may be null</b>. */
+        public final Activity get() {
+            return getActivity();
+        }
     }
 
     /**  Methods required by the PlaybackView for the VoicemailPlaybackPresenter. */
-    private class PlaybackViewImpl implements VoicemailPlaybackPresenter.PlaybackView {
+    private static final class PlaybackViewImpl implements VoicemailPlaybackPresenter.PlaybackView {
+        private final ActivityReference mActivityReference;
+        private final Context mApplicationContext;
+        private final SeekBar mPlaybackSeek;
+        private final ImageButton mStartStopButton;
+        private final ImageButton mPlaybackSpeakerphone;
+        private final ImageButton mRateDecreaseButton;
+        private final ImageButton mRateIncreaseButton;
+        private final TextViewWithMessagesController mTextController;
+
+        public PlaybackViewImpl(ActivityReference activityReference, Context applicationContext,
+                View playbackLayout) {
+            Preconditions.checkNotNull(activityReference);
+            Preconditions.checkNotNull(applicationContext);
+            Preconditions.checkNotNull(playbackLayout);
+            mActivityReference = activityReference;
+            mApplicationContext = applicationContext;
+            mPlaybackSeek = (SeekBar) playbackLayout.findViewById(R.id.playback_seek);
+            mStartStopButton = (ImageButton) playbackLayout.findViewById(
+                    R.id.playback_start_stop);
+            mPlaybackSpeakerphone = (ImageButton) playbackLayout.findViewById(
+                    R.id.playback_speakerphone);
+            mRateDecreaseButton = (ImageButton) playbackLayout.findViewById(
+                    R.id.rate_decrease_button);
+            mRateIncreaseButton = (ImageButton) playbackLayout.findViewById(
+                    R.id.rate_increase_button);
+            mTextController = new TextViewWithMessagesController(
+                    (TextView) playbackLayout.findViewById(R.id.playback_position_text),
+                    (TextView) playbackLayout.findViewById(R.id.playback_speed_text));
+        }
+
         @Override
         public void finish() {
-            getActivity().finish();
+            Activity activity = mActivityReference.get();
+            if (activity != null) {
+                activity.finish();
+            }
         }
 
         @Override
         public void runOnUiThread(Runnable runnable) {
-            getActivity().runOnUiThread(runnable);
+            Activity activity = mActivityReference.get();
+            if (activity != null) {
+                activity.runOnUiThread(runnable);
+            }
         }
 
         @Override
         public Context getDataSourceContext() {
-            return getActivity();
+            return mApplicationContext;
         }
 
         @Override
@@ -187,7 +242,7 @@
         @Override
         public void setRateDisplay(float rate, int stringResourceId) {
             mTextController.setTemporaryText(
-                    getActivity().getString(stringResourceId), 1, TimeUnit.SECONDS);
+                    mApplicationContext.getString(stringResourceId), 1, TimeUnit.SECONDS);
         }
 
         @Override
@@ -206,6 +261,16 @@
         }
 
         @Override
+        public void registerContentObserver(Uri uri, ContentObserver observer) {
+            mApplicationContext.getContentResolver().registerContentObserver(uri, false, observer);
+        }
+
+        @Override
+        public void unregisterContentObserver(ContentObserver observer) {
+            mApplicationContext.getContentResolver().unregisterContentObserver(observer);
+        }
+
+        @Override
         public void setClipPosition(int clipPositionInMillis, int clipLengthInMillis) {
             int seekBarPosition = Math.max(0, clipPositionInMillis);
             int seekBarMax = Math.max(seekBarPosition, clipLengthInMillis);
@@ -217,9 +282,26 @@
                     formatAsMinutesAndSeconds(seekBarMax - seekBarPosition));
         }
 
+        private String getString(int resId) {
+            return mApplicationContext.getString(resId);
+        }
+
         @Override
         public void setIsBuffering() {
-          mTextController.setPermanentText(getString(R.string.voicemail_buffering));
+            disableUiElements();
+            mTextController.setPermanentText(getString(R.string.voicemail_buffering));
+        }
+
+        @Override
+        public void setIsFetchingContent() {
+            disableUiElements();
+            mTextController.setPermanentText(getString(R.string.voicemail_fetching_content));
+        }
+
+        @Override
+        public void setFetchContentTimeout() {
+            disableUiElements();
+            mTextController.setPermanentText(getString(R.string.voicemail_fetching_timout));
         }
 
         @Override
@@ -228,17 +310,58 @@
         }
 
         @Override
-        public void playbackError(Exception e) {
+        public void disableUiElements() {
             mRateIncreaseButton.setEnabled(false);
             mRateDecreaseButton.setEnabled(false);
             mStartStopButton.setEnabled(false);
+            mPlaybackSpeakerphone.setEnabled(false);
             mPlaybackSeek.setProgress(0);
             mPlaybackSeek.setEnabled(false);
+        }
+
+        @Override
+        public void playbackError(Exception e) {
+            disableUiElements();
             mTextController.setPermanentText(getString(R.string.voicemail_playback_error));
             Log.e(TAG, "Could not play voicemail", e);
         }
 
         @Override
+        public void enableUiElements() {
+            mRateIncreaseButton.setEnabled(true);
+            mRateDecreaseButton.setEnabled(true);
+            mStartStopButton.setEnabled(true);
+            mPlaybackSpeakerphone.setEnabled(true);
+            mPlaybackSeek.setEnabled(true);
+        }
+
+        @Override
+        public void sendFetchVoicemailRequest(Uri voicemailUri) {
+            Intent intent = new Intent(VoicemailContract.ACTION_FETCH_VOICEMAIL, voicemailUri);
+            mApplicationContext.sendBroadcast(intent);
+        }
+
+        @Override
+        public boolean queryHasContent(Uri voicemailUri) {
+            ContentResolver contentResolver = mApplicationContext.getContentResolver();
+            Cursor cursor = contentResolver.query(
+                    voicemailUri, HAS_CONTENT_PROJECTION, null, null, null);
+            try {
+                if (cursor != null && cursor.moveToNext()) {
+                    return cursor.getInt(cursor.getColumnIndexOrThrow(
+                            VoicemailContract.Voicemails.HAS_CONTENT)) == 1;
+                }
+            } finally {
+                MoreCloseables.closeQuietly(cursor);
+            }
+            return false;
+        }
+
+        private AudioManager getAudioManager() {
+            return (AudioManager) mApplicationContext.getSystemService(Context.AUDIO_SERVICE);
+        }
+
+        @Override
         public boolean isSpeakerPhoneOn() {
             return getAudioManager().isSpeakerphoneOn();
         }
diff --git a/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java b/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
index 494888c..bd01991 100644
--- a/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
+++ b/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
@@ -23,12 +23,15 @@
 import com.android.contacts.util.BackgroundTaskService;
 import com.android.ex.variablespeed.MediaPlayerProxy;
 import com.android.ex.variablespeed.SingleThreadedMediaPlayerProxy;
+import com.google.common.base.Preconditions;
 
 import android.content.Context;
+import android.database.ContentObserver;
 import android.media.MediaPlayer;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.Handler;
 import android.view.View;
 import android.widget.SeekBar;
 
@@ -36,6 +39,7 @@
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.annotation.concurrent.GuardedBy;
@@ -73,10 +77,20 @@
         void setRateDisplay(float rate, int stringResourceId);
         void setRateIncreaseButtonListener(View.OnClickListener listener);
         void setRateDecreaseButtonListener(View.OnClickListener listener);
+        void setIsFetchingContent();
+        void disableUiElements();
+        void enableUiElements();
+        void sendFetchVoicemailRequest(Uri voicemailUri);
+        boolean queryHasContent(Uri voicemailUri);
+        void setFetchContentTimeout();
+        void registerContentObserver(Uri uri, ContentObserver observer);
+        void unregisterContentObserver(ContentObserver observer);
     }
 
     /** Update rate for the slider, 30fps. */
     private static final int SLIDER_UPDATE_PERIOD_MILLIS = 1000 / 30;
+    /** Time our ui will wait for content to be fetched before reporting not available. */
+    private static final long FETCH_CONTENT_TIMEOUT_MS = 20000;
     /**
      * If present in the saved instance bundle, we should not resume playback on
      * create.
@@ -102,6 +116,7 @@
         R.string.voicemail_speed_faster,
         R.string.voicemail_speed_fastest,
     };
+
     /**
      * Pointer into the {@link VoicemailPlaybackPresenter#PRESET_RATES} array.
      * <p>
@@ -131,6 +146,13 @@
     /** Used to run background tasks that need to interact with the ui. */
     private final BackgroundTaskService mBackgroundTaskService;
 
+    /**
+     * Used to handle the result of a successful or time-out fetch result.
+     * <p>
+     * This variable is thread-contained, accessed only on the ui thread.
+     */
+    private FetchResultHandler mFetchResultHandler;
+
     public VoicemailPlaybackPresenter(PlaybackView view, MediaPlayerProxy player,
             Uri voicemailUri, ScheduledExecutorService executorService,
             boolean startPlayingImmediately, BackgroundTaskService backgroundTaskService) {
@@ -143,6 +165,126 @@
     }
 
     public void onCreate(Bundle bundle) {
+        checkThatWeHaveContent();
+    }
+
+    /**
+     * Checks to see if we have content available for this voicemail.
+     * <p>
+     * This method will be called once, after the fragment has been created, before we know if the
+     * voicemail we've been asked to play has any content available.
+     * <p>
+     * This method will notify the user through the ui that we are fetching the content, then check
+     * to see if the content field in the db is set. If set, we proceed to
+     * {@link #postSuccessfullyFetchedContent()} method. If not set, we will make a request to fetch
+     * the content asynchronously via {@link #makeRequestForContent()}.
+     */
+    private void checkThatWeHaveContent() {
+        mView.setIsFetchingContent();
+        mBackgroundTaskService.submit(new BackgroundTask() {
+            private boolean mHasContent = false;
+
+            @Override
+            public void doInBackground() {
+                mHasContent = mView.queryHasContent(mVoicemailUri);
+            }
+
+            @Override
+            public void onPostExecute() {
+                if (mHasContent) {
+                    postSuccessfullyFetchedContent();
+                } else {
+                    makeRequestForContent();
+                }
+            }
+        }, AsyncTask.THREAD_POOL_EXECUTOR);
+    }
+
+    /**
+     * Makes a broadcast request to ask that a voicemail source fetch this content.
+     * <p>
+     * This method <b>must be called on the ui thread</b>.
+     * <p>
+     * This method will be called when we realise that we don't have content for this voicemail. It
+     * will trigger a broadcast to request that the content be downloaded. It will add a listener to
+     * the content resolver so that it will be notified when the has_content field changes. It will
+     * also set a timer. If the has_content field changes to true within the allowed time, we will
+     * proceed to {@link #postSuccessfullyFetchedContent()}. If the has_content field does not
+     * become true within the allowed time, we will update the ui to reflect the fact that content
+     * was not available.
+     */
+    private void makeRequestForContent() {
+        Handler handler = new Handler();
+        Preconditions.checkState(mFetchResultHandler == null, "mFetchResultHandler should be null");
+        mFetchResultHandler = new FetchResultHandler(handler);
+        mView.registerContentObserver(mVoicemailUri, mFetchResultHandler);
+        handler.postDelayed(mFetchResultHandler.getTimeoutRunnable(), FETCH_CONTENT_TIMEOUT_MS);
+        mView.sendFetchVoicemailRequest(mVoicemailUri);
+    }
+
+    @ThreadSafe
+    private class FetchResultHandler extends ContentObserver implements Runnable {
+        private AtomicBoolean mResultStillPending = new AtomicBoolean(true);
+        private final Handler mHandler;
+
+        public FetchResultHandler(Handler handler) {
+            super(handler);
+            mHandler = handler;
+        }
+
+        public Runnable getTimeoutRunnable() {
+            return this;
+        }
+
+        @Override
+        public void run() {
+            if (mResultStillPending.getAndSet(false)) {
+                mView.unregisterContentObserver(FetchResultHandler.this);
+                mView.setFetchContentTimeout();
+            }
+        }
+
+        public void destroy() {
+            if (mResultStillPending.getAndSet(false)) {
+                mView.unregisterContentObserver(FetchResultHandler.this);
+                mHandler.removeCallbacks(this);
+            }
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            mBackgroundTaskService.submit(new BackgroundTask() {
+                private boolean mHasContent = false;
+
+                @Override
+                public void doInBackground() {
+                    mHasContent = mView.queryHasContent(mVoicemailUri);
+                }
+
+                @Override
+                public void onPostExecute() {
+                    if (mHasContent) {
+                        if (mResultStillPending.getAndSet(false)) {
+                            mView.unregisterContentObserver(FetchResultHandler.this);
+                            postSuccessfullyFetchedContent();
+                        }
+                    }
+                }
+            }, AsyncTask.THREAD_POOL_EXECUTOR);
+        }
+    }
+
+    /**
+     * Prepares the voicemail content for playback.
+     * <p>
+     * This method will be called once we know that our voicemail has content (according to the
+     * content provider). This method will try to prepare the data source through the media player.
+     * If preparing the media player works, we will call through to
+     * {@link #postSuccessfulPrepareActions()}. If preparing the media player fails (perhaps the
+     * file the content provider points to is actually missing, perhaps it is of an unknown file
+     * format that we can't play, who knows) then we will show an error on the ui.
+     */
+    private void postSuccessfullyFetchedContent() {
         mView.setIsBuffering();
         mBackgroundTaskService.submit(new BackgroundTask() {
             private Exception mException;
@@ -169,7 +311,14 @@
         }, AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
+    /**
+     * Enables the ui, and optionally starts playback immediately.
+     * <p>
+     * This will be called once we have successfully prepared the media player, and will optionally
+     * playback immediately.
+     */
     private void postSuccessfulPrepareActions() {
+        mView.enableUiElements();
         mView.setPositionSeekListener(new PlaybackPositionListener());
         mView.setStartStopListener(new StartStopButtonListener());
         mView.setSpeakerphoneListener(new SpeakerphoneListener());
@@ -194,7 +343,14 @@
         }
     }
 
+    /**
+     * This method should be called <b>only on the ui thread</b>.
+     */
     public void onDestroy() {
+        if (mFetchResultHandler != null) {
+            mFetchResultHandler.destroy();
+            mFetchResultHandler = null;
+        }
         mPositionUpdater.stopUpdating();
         mPlayer.release();
     }
diff --git a/tests/src/com/android/contacts/model/AccountTypeTest.java b/tests/src/com/android/contacts/model/AccountTypeTest.java
index de66694..986d840 100644
--- a/tests/src/com/android/contacts/model/AccountTypeTest.java
+++ b/tests/src/com/android/contacts/model/AccountTypeTest.java
@@ -52,7 +52,7 @@
                 AccountType.getResourceText(c, packageName, externalResID, DEFAULT));
 
         // Load from the contacts package itself.
-        final int internalResId = com.android.contacts.R.string.sharedUserLabel;
+        final int internalResId = com.android.contacts.R.string.launcherDialer;
         assertEquals(c.getString(internalResId),
                 AccountType.getResourceText(c, null, internalResId, DEFAULT));
     }