Merge "Voicemail playback, with variable speed ui."
diff --git a/res/drawable-hdpi/btn_dial_action_middle_disable.9.png b/res/drawable-hdpi/btn_dial_action_middle_disable.9.png
deleted file mode 100644
index 5159c74..0000000
--- a/res/drawable-hdpi/btn_dial_action_middle_disable.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/btn_dial_action_middle_disable_focused.9.png b/res/drawable-hdpi/btn_dial_action_middle_disable_focused.9.png
deleted file mode 100644
index 46935c8..0000000
--- a/res/drawable-hdpi/btn_dial_action_middle_disable_focused.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/btn_dial_action_middle_normal.9.png b/res/drawable-hdpi/btn_dial_action_middle_normal.9.png
deleted file mode 100644
index e86afd1..0000000
--- a/res/drawable-hdpi/btn_dial_action_middle_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/btn_dial_action_middle_pressed.9.png b/res/drawable-hdpi/btn_dial_action_middle_pressed.9.png
deleted file mode 100644
index 6d428c9..0000000
--- a/res/drawable-hdpi/btn_dial_action_middle_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/btn_dial_action_middle_selected.9.png b/res/drawable-hdpi/btn_dial_action_middle_selected.9.png
deleted file mode 100644
index 678d9e0..0000000
--- a/res/drawable-hdpi/btn_dial_action_middle_selected.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/btn_dial_action_right_disable.9.png b/res/drawable-hdpi/btn_dial_action_right_disable.9.png
deleted file mode 100644
index 4844ee2..0000000
--- a/res/drawable-hdpi/btn_dial_action_right_disable.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/btn_dial_action_right_disable_focused.9.png b/res/drawable-hdpi/btn_dial_action_right_disable_focused.9.png
deleted file mode 100644
index f25cbc6..0000000
--- a/res/drawable-hdpi/btn_dial_action_right_disable_focused.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/btn_dial_action_right_normal.9.png b/res/drawable-hdpi/btn_dial_action_right_normal.9.png
deleted file mode 100644
index 54896a3..0000000
--- a/res/drawable-hdpi/btn_dial_action_right_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/btn_dial_action_right_pressed.9.png b/res/drawable-hdpi/btn_dial_action_right_pressed.9.png
deleted file mode 100644
index 27eddd3..0000000
--- a/res/drawable-hdpi/btn_dial_action_right_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/btn_dial_action_right_selected.9.png b/res/drawable-hdpi/btn_dial_action_right_selected.9.png
deleted file mode 100644
index 131f1c4..0000000
--- a/res/drawable-hdpi/btn_dial_action_right_selected.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/dial_num_1_no_vm_blk.png b/res/drawable-hdpi/dial_num_1_no_vm_blk.png
deleted file mode 100644
index 8415b05..0000000
--- a/res/drawable-hdpi/dial_num_1_no_vm_blk.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/dial_num_1_no_vm_wht.png b/res/drawable-hdpi/dial_num_1_no_vm_wht.png
deleted file mode 100644
index beaca97..0000000
--- a/res/drawable-hdpi/dial_num_1_no_vm_wht.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_call_log_header_incoming_call.png b/res/drawable-hdpi/ic_call_log_header_incoming_call.png
deleted file mode 100755
index 95c0255..0000000
--- a/res/drawable-hdpi/ic_call_log_header_incoming_call.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_call_log_header_missed_call.png b/res/drawable-hdpi/ic_call_log_header_missed_call.png
deleted file mode 100755
index 0a43e69..0000000
--- a/res/drawable-hdpi/ic_call_log_header_missed_call.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_call_log_header_outgoing_call.png b/res/drawable-hdpi/ic_call_log_header_outgoing_call.png
deleted file mode 100755
index d061ba3..0000000
--- a/res/drawable-hdpi/ic_call_log_header_outgoing_call.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_call_log_list_action_call.png b/res/drawable-hdpi/ic_call_log_list_action_call.png
deleted file mode 100644
index f47ada7..0000000
--- a/res/drawable-hdpi/ic_call_log_list_action_call.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/btn_dial_action_middle_disable.9.png b/res/drawable-mdpi/btn_dial_action_middle_disable.9.png
deleted file mode 100644
index e13b958..0000000
--- a/res/drawable-mdpi/btn_dial_action_middle_disable.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/btn_dial_action_middle_disable_focused.9.png b/res/drawable-mdpi/btn_dial_action_middle_disable_focused.9.png
deleted file mode 100644
index 7c7574f..0000000
--- a/res/drawable-mdpi/btn_dial_action_middle_disable_focused.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/btn_dial_action_middle_normal.9.png b/res/drawable-mdpi/btn_dial_action_middle_normal.9.png
deleted file mode 100644
index 575793c..0000000
--- a/res/drawable-mdpi/btn_dial_action_middle_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/btn_dial_action_middle_pressed.9.png b/res/drawable-mdpi/btn_dial_action_middle_pressed.9.png
deleted file mode 100644
index ead7039..0000000
--- a/res/drawable-mdpi/btn_dial_action_middle_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/btn_dial_action_middle_selected.9.png b/res/drawable-mdpi/btn_dial_action_middle_selected.9.png
deleted file mode 100644
index 957b7b9..0000000
--- a/res/drawable-mdpi/btn_dial_action_middle_selected.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/btn_dial_action_right_disable.9.png b/res/drawable-mdpi/btn_dial_action_right_disable.9.png
deleted file mode 100644
index de5c271..0000000
--- a/res/drawable-mdpi/btn_dial_action_right_disable.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/btn_dial_action_right_disable_focused.9.png b/res/drawable-mdpi/btn_dial_action_right_disable_focused.9.png
deleted file mode 100644
index 27bfc02..0000000
--- a/res/drawable-mdpi/btn_dial_action_right_disable_focused.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/btn_dial_action_right_normal.9.png b/res/drawable-mdpi/btn_dial_action_right_normal.9.png
deleted file mode 100644
index 515e4f4..0000000
--- a/res/drawable-mdpi/btn_dial_action_right_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/btn_dial_action_right_pressed.9.png b/res/drawable-mdpi/btn_dial_action_right_pressed.9.png
deleted file mode 100644
index 054ebef..0000000
--- a/res/drawable-mdpi/btn_dial_action_right_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/btn_dial_action_right_selected.9.png b/res/drawable-mdpi/btn_dial_action_right_selected.9.png
deleted file mode 100644
index 9c0a76b..0000000
--- a/res/drawable-mdpi/btn_dial_action_right_selected.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/dial_num_1_no_vm_blk.png b/res/drawable-mdpi/dial_num_1_no_vm_blk.png
deleted file mode 100644
index 75a8ed8..0000000
--- a/res/drawable-mdpi/dial_num_1_no_vm_blk.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/dial_num_1_no_vm_wht.png b/res/drawable-mdpi/dial_num_1_no_vm_wht.png
deleted file mode 100644
index 8871de5..0000000
--- a/res/drawable-mdpi/dial_num_1_no_vm_wht.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_call_log_header_incoming_call.png b/res/drawable-mdpi/ic_call_log_header_incoming_call.png
deleted file mode 100644
index 8b75287..0000000
--- a/res/drawable-mdpi/ic_call_log_header_incoming_call.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_call_log_header_missed_call.png b/res/drawable-mdpi/ic_call_log_header_missed_call.png
deleted file mode 100644
index 94dd69f..0000000
--- a/res/drawable-mdpi/ic_call_log_header_missed_call.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_call_log_header_outgoing_call.png b/res/drawable-mdpi/ic_call_log_header_outgoing_call.png
deleted file mode 100644
index bdedc67..0000000
--- a/res/drawable-mdpi/ic_call_log_header_outgoing_call.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_call_log_list_action_call.png b/res/drawable-mdpi/ic_call_log_list_action_call.png
deleted file mode 100644
index f47ada7..0000000
--- a/res/drawable-mdpi/ic_call_log_list_action_call.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/btn_dial_action_middle_disable.9.png b/res/drawable-xhdpi/btn_dial_action_middle_disable.9.png
deleted file mode 100644
index 6da4265..0000000
--- a/res/drawable-xhdpi/btn_dial_action_middle_disable.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/btn_dial_action_middle_disable_focused.9.png b/res/drawable-xhdpi/btn_dial_action_middle_disable_focused.9.png
deleted file mode 100644
index cddf893..0000000
--- a/res/drawable-xhdpi/btn_dial_action_middle_disable_focused.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/btn_dial_action_middle_normal.9.png b/res/drawable-xhdpi/btn_dial_action_middle_normal.9.png
deleted file mode 100644
index dc39b98..0000000
--- a/res/drawable-xhdpi/btn_dial_action_middle_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/btn_dial_action_middle_pressed.9.png b/res/drawable-xhdpi/btn_dial_action_middle_pressed.9.png
deleted file mode 100644
index f092867..0000000
--- a/res/drawable-xhdpi/btn_dial_action_middle_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/btn_dial_action_middle_selected.9.png b/res/drawable-xhdpi/btn_dial_action_middle_selected.9.png
deleted file mode 100644
index 9577eda..0000000
--- a/res/drawable-xhdpi/btn_dial_action_middle_selected.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/btn_dial_action_right_disable.9.png b/res/drawable-xhdpi/btn_dial_action_right_disable.9.png
deleted file mode 100644
index fdcd395..0000000
--- a/res/drawable-xhdpi/btn_dial_action_right_disable.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/btn_dial_action_right_disable_focused.9.png b/res/drawable-xhdpi/btn_dial_action_right_disable_focused.9.png
deleted file mode 100644
index 9f4eeb0..0000000
--- a/res/drawable-xhdpi/btn_dial_action_right_disable_focused.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/btn_dial_action_right_normal.9.png b/res/drawable-xhdpi/btn_dial_action_right_normal.9.png
deleted file mode 100644
index c6f7e09..0000000
--- a/res/drawable-xhdpi/btn_dial_action_right_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/btn_dial_action_right_pressed.9.png b/res/drawable-xhdpi/btn_dial_action_right_pressed.9.png
deleted file mode 100644
index bf99581..0000000
--- a/res/drawable-xhdpi/btn_dial_action_right_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/btn_dial_action_right_selected.9.png b/res/drawable-xhdpi/btn_dial_action_right_selected.9.png
deleted file mode 100644
index 5c06f99..0000000
--- a/res/drawable-xhdpi/btn_dial_action_right_selected.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/dial_num_1_no_vm_blk.png b/res/drawable-xhdpi/dial_num_1_no_vm_blk.png
deleted file mode 100644
index 452eed0..0000000
--- a/res/drawable-xhdpi/dial_num_1_no_vm_blk.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/dial_num_1_no_vm_wht.png b/res/drawable-xhdpi/dial_num_1_no_vm_wht.png
deleted file mode 100644
index 37d90be..0000000
--- a/res/drawable-xhdpi/dial_num_1_no_vm_wht.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_call_log_header_incoming_call.png b/res/drawable-xhdpi/ic_call_log_header_incoming_call.png
deleted file mode 100644
index cae35d1..0000000
--- a/res/drawable-xhdpi/ic_call_log_header_incoming_call.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_call_log_header_missed_call.png b/res/drawable-xhdpi/ic_call_log_header_missed_call.png
deleted file mode 100644
index cb7395c..0000000
--- a/res/drawable-xhdpi/ic_call_log_header_missed_call.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_call_log_header_outgoing_call.png b/res/drawable-xhdpi/ic_call_log_header_outgoing_call.png
deleted file mode 100644
index a17bdf3..0000000
--- a/res/drawable-xhdpi/ic_call_log_header_outgoing_call.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/btn_dial_textfield_active.xml b/res/drawable/btn_dial_textfield_active.xml
deleted file mode 100644
index f3af301..0000000
--- a/res/drawable/btn_dial_textfield_active.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true"
-        android:drawable="@drawable/btn_dial_textfield_pressed" />
-    <item android:state_focused="true"
-        android:drawable="@drawable/btn_dial_textfield_selected" />
-    <item
-        android:drawable="@drawable/btn_dial_textfield_activated" />
-</selector>
-
diff --git a/res/layout-sw580dp/group_detail_fragment.xml b/res/layout-sw580dp/group_detail_fragment.xml
index a824319..7c65036 100644
--- a/res/layout-sw580dp/group_detail_fragment.xml
+++ b/res/layout-sw580dp/group_detail_fragment.xml
@@ -37,8 +37,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:paddingLeft="@dimen/group_detail_border_padding"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textColor="?android:attr/textColorSecondary" />
+        android:textAppearance="?android:attr/textAppearanceSmall"
+        android:textColor="?android:attr/textColorTertiary" />
 
     <View
         android:layout_width="match_parent"
diff --git a/res/layout/call_log_action_group.xml b/res/layout/call_log_action_group.xml
deleted file mode 100644
index fa6bb79..0000000
--- a/res/layout/call_log_action_group.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <ImageView
-        android:id="@+id/groupIndicator"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:paddingLeft="12dip"
-        android:paddingRight="13dip"
-        android:layout_alignParentRight="true"
-        android:gravity="center_vertical"
-        android:src="@*android:drawable/expander_ic_minimized"
-    />
-
-    <View android:id="@+id/divider"
-        android:layout_width="1px"
-        android:layout_height="match_parent"
-        android:layout_marginTop="5dip"
-        android:layout_marginBottom="5dip"
-        android:layout_toLeftOf="@id/groupIndicator"
-        android:layout_marginLeft="11dip"
-        android:background="@drawable/divider_vertical_dark"
-    />
-
-</merge>
diff --git a/res/layout/call_log_fragment.xml b/res/layout/call_log_fragment.xml
index 2a27fcd..573969b 100644
--- a/res/layout/call_log_fragment.xml
+++ b/res/layout/call_log_fragment.xml
@@ -14,21 +14,29 @@
      limitations under the License.
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:orientation="vertical"
 >
-    <ListView android:id="@android:id/list"
+    <include layout="@layout/call_log_voicemail_status"/>
+    <FrameLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:scrollbarStyle="outsideOverlay"
-    />
+        android:layout_height="wrap_content"
+    >
+        <ListView android:id="@android:id/list"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:scrollbarStyle="outsideOverlay"
+        />
 
-    <TextView android:id="@android:id/empty"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:text="@string/recentCalls_empty"
-        android:gravity="center"
-        android:textAppearance="?android:attr/textAppearanceLarge"
-    />
-</FrameLayout>
+        <TextView android:id="@android:id/empty"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:text="@string/recentCalls_empty"
+            android:gravity="center"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+        />
+    </FrameLayout>
+</LinearLayout>
+
diff --git a/res/layout/call_log_voicemail_status.xml b/res/layout/call_log_voicemail_status.xml
new file mode 100644
index 0000000..1abe998
--- /dev/null
+++ b/res/layout/call_log_voicemail_status.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/voicemail_status"
+    android:layout_width="match_parent"
+    android:layout_height="?attr/call_log_voicemail_status_height"
+    android:layout_alignParentLeft="true"
+    android:layout_alignParentBottom="true"
+    android:background="?attr/call_log_voicemail_status_background_color"
+    android:baselineAligned="false">
+    <TextView
+        android:id="@+id/voicemail_status_message"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingLeft="14dip"
+        android:paddingRight="14dip"
+        android:textColor="?attr/call_log_voicemail_status_text_color"
+        android:layout_gravity="left"
+        android:layout_weight="5"/>
+    <View android:id="@+id/divider"
+        android:layout_width="1px"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="5dip"
+        android:layout_marginBottom="5dip"
+        android:layout_marginLeft="11dip"
+        android:background="@drawable/divider_vertical_dark"/>
+    <TextView
+        android:id="@+id/voicemail_status_action"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="right"
+        android:paddingLeft="14dip"
+        android:paddingRight="14dip"
+        android:textColor="?attr/call_log_voicemail_status_text_color"
+        android:gravity="right"
+        android:layout_alignParentRight="true"
+        android:clickable="true"
+    />
+</LinearLayout>
diff --git a/res/layout/edit_date_picker.xml b/res/layout/edit_date_picker.xml
index ca5e281..c18d607 100644
--- a/res/layout/edit_date_picker.xml
+++ b/res/layout/edit_date_picker.xml
@@ -23,5 +23,6 @@
     android:layout_height="wrap_content"
     android:layout_weight="1"
     android:layout_marginLeft="@dimen/editor_field_left_padding"
+    android:layout_marginRight="@dimen/editor_field_right_padding"
     android:textAppearance="?android:attr/textAppearanceMedium"
     style="@android:style/Widget.Holo.Light.Spinner" />
\ No newline at end of file
diff --git a/res/layout/edit_field_list.xml b/res/layout/edit_field_list.xml
index ba715c7..f9e6565 100644
--- a/res/layout/edit_field_list.xml
+++ b/res/layout/edit_field_list.xml
@@ -23,4 +23,5 @@
     android:layout_weight="1"
     android:layout_height="wrap_content"
     android:paddingLeft="@dimen/editor_field_left_padding"
+    android:paddingRight="@dimen/editor_field_right_padding"
     android:orientation="vertical" />
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 207a255..3bc1bc6 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -50,6 +50,9 @@
     <!-- Left padding of a field in the Editor -->
     <dimen name="editor_field_left_padding">5dip</dimen>
 
+    <!-- Right padding of a field in the Editor -->
+    <dimen name="editor_field_right_padding">5dip</dimen>
+
     <!-- Top padding of a field in the Editor -->
     <dimen name="editor_field_top_padding">10dip</dimen>
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 534fc4e..54bb5ed 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1569,6 +1569,12 @@
       (Contacts themselves will not be deleted.)
     </string>
 
+    <!-- Subtitle of the group detail page that describes how many people are in the current group [CHAR LIMIT=30] -->
+    <plurals name="num_contacts_in_group">
+        <item quantity="one"><xliff:g id="count">%1$d</xliff:g> person from <xliff:g id="account_type">%2$s</xliff:g></item>
+        <item quantity="other"><xliff:g id="count">%1$d</xliff:g> people from <xliff:g id="account_type">%2$s</xliff:g></item>
+    </plurals>
+
     <!-- Toast displayed when the user creates a new contact and attempts to join it
       with another before entering any data  [CHAR LIMIT=256] -->
     <string name="toast_join_with_empty_contact">Please enter contact name before joining
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 4638b2e..43ea301 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -49,6 +49,10 @@
         <item name="call_log_primary_background_color">#000000</item>
         <item name="call_log_secondary_text_color">#FFFFFF</item>
         <item name="call_log_secondary_background_color">#333333</item>
+        <!-- VoicemailStatus -->
+        <item name="call_log_voicemail_status_height">40dip</item>
+        <item name="call_log_voicemail_status_background_color">#FFFFE0</item>
+        <item name="call_log_voicemail_status_text_color">#000000</item>
     </style>
 
     <style name="CallDetailActivityTheme" parent="android:Theme.Holo">
@@ -161,6 +165,12 @@
         <attr name="call_log_list_header_background" format="reference" />
     </declare-styleable>
 
+    <declare-styleable name="VoicemailStatus">
+        <attr name="call_log_voicemail_status_height" format="dimension" />
+        <attr name="call_log_voicemail_status_background_color" format="color" />
+        <attr name="call_log_voicemail_status_text_color" format="color" />
+    </declare-styleable>
+
     <style name="PeopleTheme" parent="android:Theme.Holo.Light.SplitActionBarWhenNarrow">
         <item name="list_item_height">?android:attr/listPreferredItemHeight</item>
         <item name="activated_background">@drawable/list_item_activated_background</item>
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index 11888a5..9fd1b03 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -109,7 +109,7 @@
         PhoneLookup.LABEL,
         PhoneLookup.NUMBER,
         PhoneLookup.NORMALIZED_NUMBER,
-        PhoneLookup.PHOTO_ID,
+        PhoneLookup.PHOTO_URI,
     };
     static final int COLUMN_INDEX_ID = 0;
     static final int COLUMN_INDEX_NAME = 1;
@@ -117,7 +117,7 @@
     static final int COLUMN_INDEX_LABEL = 3;
     static final int COLUMN_INDEX_NUMBER = 4;
     static final int COLUMN_INDEX_NORMALIZED_NUMBER = 5;
-    static final int COLUMN_INDEX_PHOTO_ID = 6;
+    static final int COLUMN_INDEX_PHOTO_URI = 6;
 
     @Override
     protected void onCreate(Bundle icicle) {
@@ -249,7 +249,7 @@
         // We know that all calls are from the same number and the same contact, so pick the first.
         mNumber = details[0].number.toString();
         final long personId = details[0].personId;
-        final long photoId = details[0].photoId;
+        final Uri photoUri = details[0].photoUri;
 
         // Set the details header, based on the first phone call.
         mPhoneCallDetailsHelper.setPhoneCallDetails(mPhoneCallDetailsViews,
@@ -356,7 +356,7 @@
         ListView historyList = (ListView) findViewById(R.id.history);
         historyList.setAdapter(
                 new CallDetailHistoryAdapter(this, mInflater, mCallTypeHelper, details));
-        loadContactPhotos(photoId);
+        loadContactPhotos(photoUri);
     }
 
     /** Return the phone call details for a given call log URI. */
@@ -385,7 +385,7 @@
             int numberType = 0;
             CharSequence numberLabel = "";
             long personId = -1L;
-            long photoId = 0L;
+            Uri photoUri = null;
             // If this is not a regular number, there is no point in looking it up in the contacts.
             if (!mPhoneNumberHelper.canPlaceCallsTo(number)) {
                 numberText = mPhoneNumberHelper.getDisplayNumber(number, null);
@@ -399,7 +399,8 @@
                     if (phonesCursor != null && phonesCursor.moveToFirst()) {
                         personId = phonesCursor.getLong(COLUMN_INDEX_ID);
                         nameText = phonesCursor.getString(COLUMN_INDEX_NAME);
-                        photoId = phonesCursor.getLong(COLUMN_INDEX_PHOTO_ID);
+                        String photoUriString = phonesCursor.getString(COLUMN_INDEX_PHOTO_URI);
+                        photoUri = photoUriString == null ? null : Uri.parse(photoUriString);
                         candidateNumberText = PhoneNumberUtils.formatNumber(
                                 phonesCursor.getString(COLUMN_INDEX_NUMBER),
                                 phonesCursor.getString(COLUMN_INDEX_NORMALIZED_NUMBER),
@@ -419,7 +420,7 @@
                 }
             }
             return new PhoneCallDetails(number, numberText, new int[]{ callType }, date, duration,
-                    nameText, numberType, numberLabel, personId, photoId);
+                    nameText, numberType, numberLabel, personId, photoUri);
         } finally {
             if (callCursor != null) {
                 callCursor.close();
@@ -428,8 +429,8 @@
     }
 
     /** Load the contact photos and places them in the corresponding views. */
-    private void loadContactPhotos(final long photoId) {
-        mContactPhotoManager.loadPhoto(mContactBackgroundView, photoId);
+    private void loadContactPhotos(Uri photoUri) {
+        mContactPhotoManager.loadPhoto(mContactBackgroundView, photoUri);
     }
 
     private String getVoicemailNumber() {
diff --git a/src/com/android/contacts/PhoneCallDetails.java b/src/com/android/contacts/PhoneCallDetails.java
index 6ab47aa..d4786d9 100644
--- a/src/com/android/contacts/PhoneCallDetails.java
+++ b/src/com/android/contacts/PhoneCallDetails.java
@@ -16,6 +16,7 @@
 
 package com.android.contacts;
 
+import android.net.Uri;
 import android.provider.CallLog.Calls;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 
@@ -45,19 +46,22 @@
     public final CharSequence numberLabel;
     /** The id of the contact associated with this phone call. */
     public final long personId;
-    /** The photo id of the contact associated with this phone call. */
-    public final long photoId;
+    /**
+     * The photo uri of the picture of the contact that is associated with this phone call or
+     * null if there is none.
+     */
+    public final Uri photoUri;
 
     /** Create the details for a call with a number not associated with a contact. */
     public PhoneCallDetails(CharSequence number, CharSequence formattedNumber, int[] callTypes,
             long date, long duration) {
-        this(number, formattedNumber, callTypes, date, duration, "", 0, "", -1L, 0L);
+        this(number, formattedNumber, callTypes, date, duration, "", 0, "", -1L, null);
     }
 
     /** Create the details for a call with a number associated with a contact. */
     public PhoneCallDetails(CharSequence number, CharSequence formattedNumber, int[] callTypes,
             long date, long duration, CharSequence name, int numberType, CharSequence numberLabel,
-            long personId, long photoId) {
+            long personId, Uri photoUri) {
         this.number = number;
         this.formattedNumber = formattedNumber;
         this.callTypes = callTypes;
@@ -67,6 +71,6 @@
         this.numberType = numberType;
         this.numberLabel = numberLabel;
         this.personId = personId;
-        this.photoId = photoId;
+        this.photoUri = photoUri;
     }
 }
diff --git a/src/com/android/contacts/activities/ContactDetailActivity.java b/src/com/android/contacts/activities/ContactDetailActivity.java
index 0637fd5..de262b2 100644
--- a/src/com/android/contacts/activities/ContactDetailActivity.java
+++ b/src/com/android/contacts/activities/ContactDetailActivity.java
@@ -172,9 +172,8 @@
     }
 
     @Override
-    public void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData,
-            boolean globalSearch) {
-        // Ignore search key press
+    public boolean onSearchRequested() {
+        return true; // Don't respond to the search key.
     }
 
     @Override
diff --git a/src/com/android/contacts/activities/ContactEditorActivity.java b/src/com/android/contacts/activities/ContactEditorActivity.java
index 1ee7f1d..6655c81 100644
--- a/src/com/android/contacts/activities/ContactEditorActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorActivity.java
@@ -120,9 +120,8 @@
     }
 
     @Override
-    public void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData,
-            boolean globalSearch) {
-        // Ignore search key press
+    public boolean onSearchRequested() {
+        return true; // Don't respond to the search key.
     }
 
     @Override
diff --git a/src/com/android/contacts/activities/GroupDetailActivity.java b/src/com/android/contacts/activities/GroupDetailActivity.java
index 635c130..dcd35fa 100644
--- a/src/com/android/contacts/activities/GroupDetailActivity.java
+++ b/src/com/android/contacts/activities/GroupDetailActivity.java
@@ -92,8 +92,7 @@
     }
 
     @Override
-    public void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData,
-            boolean globalSearch) {
-        // Ignore search key press
+    public boolean onSearchRequested() {
+        return true; // Don't respond to the search key.
     }
 }
diff --git a/src/com/android/contacts/activities/GroupEditorActivity.java b/src/com/android/contacts/activities/GroupEditorActivity.java
index ecadcec..b2553a4 100644
--- a/src/com/android/contacts/activities/GroupEditorActivity.java
+++ b/src/com/android/contacts/activities/GroupEditorActivity.java
@@ -83,9 +83,8 @@
     }
 
     @Override
-    public void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData,
-            boolean globalSearch) {
-        // Ignore search key press
+    public boolean onSearchRequested() {
+        return true; // Don't respond to the search key.
     }
 
     @Override
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index 77b978d..ee36d8f 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -90,6 +90,7 @@
 import android.widget.Toast;
 
 import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Displays a list to browse contacts. For xlarge screens, this also displays a detail-pane on
@@ -101,6 +102,7 @@
         ContactListFilterController.ContactListFilterListener, ProviderStatusListener {
 
     private static final String TAG = "PeopleActivity";
+    private static final Boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE
 
     private static final int SUBACTIVITY_NEW_CONTACT = 2;
     private static final int SUBACTIVITY_EDIT_CONTACT = 3;
@@ -118,8 +120,6 @@
 
     private ActionBarAdapter mActionBarAdapter;
 
-    private boolean mSearchMode;
-
     private ContactDetailFragment mContactDetailFragment;
     private ContactDetailUpdatesFragment mContactDetailUpdatesFragment;
     private final ContactDetailFragmentListener mContactDetailFragmentListener =
@@ -136,8 +136,6 @@
     private StrequentContactListFragment.Listener mFavoritesFragmentListener =
             new StrequentContactListFragmentListener();
 
-    private boolean mSearchInitiated;
-
     private ContactListFilterController mContactListFilterController;
 
     private ContactsUnavailableFragment mContactsUnavailableFragment;
@@ -182,13 +180,24 @@
      */
     private boolean mFragmentInitialized;
 
+    /** Sequential ID assigned to each instance; used for logging */
+    private final int mInstanceId;
+    private static final AtomicInteger sNextInstanceId = new AtomicInteger();
+
     public PeopleActivity() {
+        mInstanceId = sNextInstanceId.getAndIncrement();
         mIntentResolver = new ContactsIntentResolver(this);
         mContactListFilterController = new ContactListFilterController(this);
         mContactListFilterController.addListener(this);
         mProviderStatusLoader = new ProviderStatusLoader(this);
     }
 
+    @Override
+    public String toString() {
+        // Shown on logcat
+        return String.format("%s@%d", getClass().getSimpleName(), mInstanceId);
+    }
+
     public boolean areContactsAvailable() {
         return mProviderStatus == ProviderStatus.STATUS_NORMAL;
     }
@@ -225,7 +234,7 @@
     protected void onCreate(Bundle savedState) {
         super.onCreate(savedState);
 
-        if (!processIntent()) {
+        if (!processIntent(false)) {
             finish();
             return;
         }
@@ -237,7 +246,7 @@
     @Override
     protected void onNewIntent(Intent intent) {
         setIntent(intent);
-        if (!processIntent()) {
+        if (!processIntent(true)) {
             finish();
             return;
         }
@@ -252,13 +261,18 @@
      * Resolve the intent and initialize {@link #mRequest}, and launch another activity if redirect
      * is needed.
      *
+     * @param forNewIntent set true if it's called from {@link #onNewIntent(Intent)}.
      * @return {@code true} if {@link PeopleActivity} should continue running.  {@code false}
      *         if it shouldn't, in which case the caller should finish() itself and shouldn't do
      *         farther initialization.
      */
-    private boolean processIntent() {
+    private boolean processIntent(boolean forNewIntent) {
         // Extract relevant information from the intent
         mRequest = mIntentResolver.resolveIntent(getIntent());
+        if (DEBUG) {
+            Log.d(TAG, this + " processIntent: forNewIntent=" + forNewIntent
+                    + " intent=" + getIntent() + " request=" + mRequest);
+        }
         if (!mRequest.isValid()) {
             setResult(RESULT_CANCELED);
             return false;
@@ -452,6 +466,7 @@
         if (fromRequest) {
             ContactListFilter filter = null;
             int actionCode = mRequest.getActionCode();
+            boolean searchMode = mRequest.isSearchMode();
             switch (actionCode) {
                 case ContactsRequest.ACTION_ALL_CONTACTS:
                     filter = ContactListFilter.createFilterWithType(
@@ -476,25 +491,17 @@
                     }
             }
 
-            mSearchMode = mRequest.isSearchMode();
             if (filter != null) {
                 mContactListFilterController.setContactListFilter(filter, false);
-                mSearchMode = false;
-            } else if (mRequest.getActionCode() == ContactsRequest.ACTION_ALL_CONTACTS) {
-                mContactListFilterController.setContactListFilter(
-                        ContactListFilter.createFilterWithType(
-                        ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS), false);
+                searchMode = false;
             }
 
             if (mRequest.getContactUri() != null) {
-                mSearchMode = false;
+                searchMode = false;
             }
 
-            mAllFragment.setContactsRequest(mRequest);
+            mActionBarAdapter.setSearchMode(searchMode);
             configureContactListFragmentForRequest();
-
-        } else {
-            mSearchMode = mActionBarAdapter.isSearchMode();
         }
 
         configureContactListFragment();
@@ -787,13 +794,15 @@
     }
 
     private void configureContactListFragmentForRequest() {
+        mAllFragment.setContactsRequest(mRequest);
+
         Uri contactUri = mRequest.getContactUri();
         if (contactUri != null) {
             mAllFragment.setSelectedContactUri(contactUri);
         }
 
-        mAllFragment.setSearchMode(mRequest.isSearchMode());
-        mAllFragment.setQueryString(mRequest.getQueryString(), false);
+        mAllFragment.setSearchMode(mActionBarAdapter.isSearchMode());
+        mAllFragment.setQueryString(mActionBarAdapter.getQueryString(), false);
 
         if (mRequest.isDirectorySearchEnabled()) {
             mAllFragment.setDirectorySearchMode(DirectoryListLoader.SEARCH_MODE_DEFAULT);
@@ -807,10 +816,11 @@
     }
 
     private void configureContactListFragment() {
-        mAllFragment.setSearchMode(mSearchMode);
+        final boolean searchMode = mActionBarAdapter.isSearchMode();
+        mAllFragment.setSearchMode(searchMode);
 
         final boolean useTwoPane = PhoneCapabilityTester.isUsingTwoPanes(this);
-        mAllFragment.setVisibleScrollbarEnabled(!mSearchMode);
+        mAllFragment.setVisibleScrollbarEnabled(!searchMode);
         mAllFragment.setVerticalScrollbarPosition(
                 useTwoPane
                         ? View.SCROLLBAR_POSITION_LEFT
@@ -1322,13 +1332,9 @@
     }
 
     @Override
-    public void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData,
-            boolean globalSearch) {
-        if (mAllFragment != null && mAllFragment.isAdded() && !globalSearch) {
-            mAllFragment.startSearch(initialQuery);
-        } else {
-            super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch);
-        }
+    public boolean onSearchRequested() { // Search key pressed.
+        mActionBarAdapter.setSearchMode(true);
+        return true;
     }
 
     @Override
@@ -1419,12 +1425,6 @@
                         mActionBarAdapter.setQueryString(query);
                         mActionBarAdapter.setSearchMode(true);
                         return true;
-                    } else if (!mRequest.isSearchMode()) {
-                        if (!mSearchInitiated) {
-                            mSearchInitiated = true;
-                            startSearch(query, false, null, false);
-                            return true;
-                        }
                     }
                 }
             }
@@ -1435,7 +1435,7 @@
 
     @Override
     public void onBackPressed() {
-        if (mSearchMode && mActionBarAdapter != null) {
+        if (mActionBarAdapter.isSearchMode()) {
             mActionBarAdapter.setSearchMode(false);
         } else {
             super.onBackPressed();
@@ -1460,7 +1460,6 @@
     @Override
     protected void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
-        outState.putBoolean(KEY_SEARCH_MODE, mSearchMode);
         mActionBarAdapter.onSaveInstanceState(outState);
         if (mContactDetailLayoutController != null) {
             mContactDetailLayoutController.onSaveInstanceState(outState);
@@ -1475,7 +1474,6 @@
     @Override
     protected void onRestoreInstanceState(Bundle inState) {
         super.onRestoreInstanceState(inState);
-        mSearchMode = inState.getBoolean(KEY_SEARCH_MODE);
         if (mContactDetailLayoutController != null) {
             mContactDetailLayoutController.onRestoreInstanceState(inState);
         }
diff --git a/src/com/android/contacts/calllog/CallLogFragment.java b/src/com/android/contacts/calllog/CallLogFragment.java
index 783d06b..7db5281 100644
--- a/src/com/android/contacts/calllog/CallLogFragment.java
+++ b/src/com/android/contacts/calllog/CallLogFragment.java
@@ -25,6 +25,7 @@
 import com.android.contacts.R;
 import com.android.contacts.activities.DialtactsActivity;
 import com.android.contacts.activities.DialtactsActivity.ViewPagerVisibilityListener;
+import com.android.contacts.calllog.VoicemailStatusHelper.StatusMessage;
 import com.android.contacts.util.ExpirableCache;
 import com.android.internal.telephony.CallerInfo;
 import com.google.common.annotations.VisibleForTesting;
@@ -63,8 +64,10 @@
 import android.view.ViewTreeObserver;
 import android.widget.ListView;
 import android.widget.QuickContactBadge;
+import android.widget.TextView;
 
 import java.util.LinkedList;
+import java.util.List;
 
 
 /**
@@ -126,7 +129,7 @@
                 PhoneLookup.LABEL,
                 PhoneLookup.NUMBER,
                 PhoneLookup.NORMALIZED_NUMBER,
-                PhoneLookup.PHOTO_ID,
+                PhoneLookup.PHOTO_THUMBNAIL_URI,
                 PhoneLookup.LOOKUP_KEY};
 
         public static final int PERSON_ID = 0;
@@ -135,7 +138,7 @@
         public static final int LABEL = 3;
         public static final int MATCHED_NUMBER = 4;
         public static final int NORMALIZED_NUMBER = 5;
-        public static final int PHOTO_ID = 6;
+        public static final int THUMBNAIL_URI = 6;
         public static final int LOOKUP_KEY = 7;
     }
 
@@ -151,6 +154,11 @@
 
     private boolean mShowOptionsMenu;
 
+    private VoicemailStatusHelper mVoicemailStatusHelper;
+    private View mStatusMessageView;
+    private TextView mStatusMessageText;
+    private TextView mStatusMessageAction;
+
     public static final class ContactInfo {
         public long personId;
         public String name;
@@ -159,7 +167,7 @@
         public String number;
         public String formattedNumber;
         public String normalizedNumber;
-        public long photoId;
+        public Uri thumbnailUri;
         public String lookupKey;
 
         public static ContactInfo EMPTY = new ContactInfo();
@@ -171,7 +179,7 @@
         public String name;
         public int numberType;
         public String numberLabel;
-        public long photoId;
+        public Uri thumbnailUri;
         public String lookupKey;
     }
 
@@ -307,8 +315,7 @@
                     resources.getDrawable(R.drawable.ic_call_outgoing_holo_dark),
                     resources.getDrawable(R.drawable.ic_call_missed_holo_dark),
                     resources.getDrawable(R.drawable.ic_call_voicemail_holo_dark));
-            Drawable callDrawable = resources.getDrawable(
-                    R.drawable.ic_call_log_list_action_call);
+            Drawable callDrawable = resources.getDrawable(R.drawable.ic_dial_action_call);
             Drawable playDrawable = resources.getDrawable(
                     R.drawable.ic_call_log_list_action_play);
 
@@ -377,15 +384,15 @@
             mContactInfoCache.expireAll();
         }
 
-        private void enqueueRequest(String number, boolean immediate, int position,
-                String name, int numberType, String numberLabel, long photoId, String lookupKey) {
+        private void enqueueRequest(String number, boolean immediate, int position, String name,
+                int numberType, String numberLabel, Uri thumbnailUri, String lookupKey) {
             CallerInfoQuery ciq = new CallerInfoQuery();
             ciq.number = number;
             ciq.position = position;
             ciq.name = name;
             ciq.numberType = numberType;
             ciq.numberLabel = numberLabel;
-            ciq.photoId = photoId;
+            ciq.thumbnailUri = thumbnailUri;
             ciq.lookupKey = lookupKey;
             synchronized (mRequests) {
                 mRequests.add(ciq);
@@ -466,8 +473,11 @@
                             info.number = dataTableCursor.getString(
                                     dataTableCursor.getColumnIndex(Data.DATA1));
                             info.normalizedNumber = null;  // meaningless for SIP addresses
-                            info.photoId = dataTableCursor.getLong(
-                                    dataTableCursor.getColumnIndex(Data.PHOTO_ID));
+                            final String thumbnailUriString = dataTableCursor.getString(
+                                    dataTableCursor.getColumnIndex(Data.PHOTO_THUMBNAIL_URI));
+                            info.thumbnailUri = thumbnailUriString == null
+                                    ? null
+                                    : Uri.parse(thumbnailUriString);
                             info.lookupKey = dataTableCursor.getString(
                                     dataTableCursor.getColumnIndex(Data.LOOKUP_KEY));
 
@@ -494,7 +504,11 @@
                                     .getString(PhoneQuery.MATCHED_NUMBER);
                             info.normalizedNumber = phonesCursor
                                     .getString(PhoneQuery.NORMALIZED_NUMBER);
-                            info.photoId = phonesCursor.getLong(PhoneQuery.PHOTO_ID);
+                            final String thumbnailUriString = phonesCursor.getString(
+                                    PhoneQuery.THUMBNAIL_URI);
+                            info.thumbnailUri = thumbnailUriString == null
+                                    ? null
+                                    : Uri.parse(thumbnailUriString);
                             info.lookupKey = phonesCursor.getString(PhoneQuery.LOOKUP_KEY);
 
                             infoUpdated = true;
@@ -735,7 +749,7 @@
                 mContactInfoCache.put(number, info);
                 Log.d(TAG, "Contact info missing: " + number);
                 // Request the contact details immediately since they are currently missing.
-                enqueueRequest(number, true, c.getPosition(), "", 0, "", 0L, "");
+                enqueueRequest(number, true, c.getPosition(), "", 0, "", null, "");
             } else if (info != ContactInfo.EMPTY) { // Has been queried
                 if (cachedInfo.isExpired()) {
                     Log.d(TAG, "Contact info expired: " + number);
@@ -745,7 +759,7 @@
                     // The contact info is no longer up to date, we should request it. However, we
                     // do not need to request them immediately.
                     enqueueRequest(number, false, c.getPosition(), info.name, info.type, info.label,
-                            info.photoId, info.lookupKey);
+                            info.thumbnailUri, info.lookupKey);
                 }
 
                 // Format and cache phone number for found contact
@@ -763,7 +777,7 @@
             final String name = info.name;
             final int ntype = info.type;
             final String label = info.label;
-            final long photoId = info.photoId;
+            final Uri thumbnailUri = info.thumbnailUri;
             final String lookupKey = info.lookupKey;
             // Assumes the call back feature is on most of the
             // time. For private and unknown numbers: hide it.
@@ -777,7 +791,7 @@
                 details = new PhoneCallDetails(number, formattedNumber, callTypes, date, duration);
             } else {
                 details = new PhoneCallDetails(number, formattedNumber, callTypes, date, duration,
-                        name, ntype, label, personId, photoId);
+                        name, ntype, label, personId, thumbnailUri);
             }
 
             final boolean isNew = isNewSection(c);
@@ -787,7 +801,7 @@
             final boolean isHighlighted = isNew;
             mCallLogViewsHelper.setPhoneCallDetails(views, details, useIcons, isHighlighted);
             if (views.photoView != null) {
-                bindQuickContact(views.photoView, photoId, personId, lookupKey);
+                bindQuickContact(views.photoView, thumbnailUri, personId, lookupKey);
             }
 
 
@@ -817,10 +831,10 @@
             return callTypes;
         }
 
-        private void bindQuickContact(QuickContactBadge view, long photoId, long contactId,
+        private void bindQuickContact(QuickContactBadge view, Uri thumbnailUri, long contactId,
                 String lookupKey) {
             view.assignContactUri(getContactUri(contactId, lookupKey));
-            mContactPhotoManager.loadPhoto(view, photoId);
+            mContactPhotoManager.loadPhoto(view, thumbnailUri);
         }
 
         private Uri getContactUri(long contactId, String lookupKey) {
@@ -875,7 +889,12 @@
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
-        return inflater.inflate(R.layout.call_log_fragment, container, false);
+        View view = inflater.inflate(R.layout.call_log_fragment, container, false);
+        mVoicemailStatusHelper = new VoicemailStatusHelperImpl(getActivity().getContentResolver());
+        mStatusMessageView = view.findViewById(R.id.voicemail_status);
+        mStatusMessageText = (TextView) view.findViewById(R.id.voicemail_status_message);
+        mStatusMessageAction = (TextView) view.findViewById(R.id.voicemail_status_action);
+        return view;
     }
 
     @Override
@@ -901,12 +920,42 @@
 
         startQuery();
         resetNewCallsFlag();
-
+        updateVoicemailStatusMessage();
         super.onResume();
 
         mAdapter.mPreDrawListener = null; // Let it restart the thread after next draw
     }
 
+    private void updateVoicemailStatusMessage() {
+        // TODO: make call to mVoicemailStatusHelper asynchronously.
+        List<StatusMessage> messages = mVoicemailStatusHelper.getStatusMessages();
+        if (messages.size() == 0) {
+            mStatusMessageView.setVisibility(View.GONE);
+        } else {
+            mStatusMessageView.setVisibility(View.VISIBLE);
+            // TODO: Change the code to show all messages. For now just pick the first message.
+            final StatusMessage message = messages.get(0);
+            if (message.statusMessageId != -1) {
+                mStatusMessageText.setText(message.statusMessageId);
+            }
+            if (message.actionMessageId != -1) {
+                mStatusMessageAction.setText(message.actionMessageId);
+            }
+            if (message.actionUri != null) {
+                mStatusMessageAction.setClickable(true);
+                mStatusMessageAction.setOnClickListener(new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        getActivity().startActivity(
+                                new Intent(Intent.ACTION_VIEW, message.actionUri));
+                    }
+                });
+            } else {
+                mStatusMessageAction.setClickable(false);
+            }
+        }
+    }
+
     @Override
     public void onPause() {
         super.onPause();
diff --git a/src/com/android/contacts/calllog/VoicemailStatusHelper.java b/src/com/android/contacts/calllog/VoicemailStatusHelper.java
index d4a3965..607d31a 100644
--- a/src/com/android/contacts/calllog/VoicemailStatusHelper.java
+++ b/src/com/android/contacts/calllog/VoicemailStatusHelper.java
@@ -30,7 +30,7 @@
  * this class to check if any message needs to be shown.
  */
 public interface VoicemailStatusHelper {
-    public class Message {
+    public class StatusMessage {
         /** Package of the source on behalf of which this message has to be shown.*/
         public final String sourcePackage;
         /** The string resource id of the status message that should be shown. */
@@ -39,7 +39,7 @@
         public final int actionMessageId;
         /** URI for the corrective action, where applicable. Null if no action URI is available. */
         public final Uri actionUri;
-        public Message(String sourcePackage, int statusMessageId, int actionMessageId,
+        public StatusMessage(String sourcePackage, int statusMessageId, int actionMessageId,
                 Uri actionUri) {
             this.sourcePackage = sourcePackage;
             this.statusMessageId = statusMessageId;
@@ -52,5 +52,5 @@
      * Returns a list of messages, in the order or priority that should be shown to the user. An
      * empty list is returned if no message needs to be shown.
      */
-    public List<Message> getStatusMessages();
+    public List<StatusMessage> getStatusMessages();
 }
diff --git a/src/com/android/contacts/calllog/VoicemailStatusHelperImpl.java b/src/com/android/contacts/calllog/VoicemailStatusHelperImpl.java
index 9738fd7..690f102 100644
--- a/src/com/android/contacts/calllog/VoicemailStatusHelperImpl.java
+++ b/src/com/android/contacts/calllog/VoicemailStatusHelperImpl.java
@@ -133,26 +133,26 @@
         mContentResolver = contentResolver;
     }
 
-    /** A wrapper on {@link Message} which additionally stores the priority of the message. */
-    private static class MessageWrapper {
-        private final Message mMessage;
+    /** A wrapper on {@link StatusMessage} which additionally stores the priority of the message. */
+    private static class MessageStatusWithPriority {
+        private final StatusMessage mMessage;
         private final int mPriority;
 
-        public MessageWrapper(Message message, int priority) {
+        public MessageStatusWithPriority(StatusMessage message, int priority) {
             mMessage = message;
             mPriority = priority;
         }
     }
 
     @Override
-    public List<Message> getStatusMessages() {
+    public List<StatusMessage> getStatusMessages() {
         Cursor cursor = null;
         try {
             cursor = mContentResolver.query(Status.CONTENT_URI, PROJECTION, null, null, null);
-            List<MessageWrapper> messages =
-                    new ArrayList<VoicemailStatusHelperImpl.MessageWrapper>();
+            List<MessageStatusWithPriority> messages =
+                    new ArrayList<VoicemailStatusHelperImpl.MessageStatusWithPriority>();
             while(cursor.moveToNext()) {
-                MessageWrapper message = getMessageForStatusEntry(cursor);
+                MessageStatusWithPriority message = getMessageForStatusEntry(cursor);
                 if (message != null) {
                     messages.add(message);
                 }
@@ -164,16 +164,16 @@
         }
     }
 
-    private List<Message> reorderMessages(List<MessageWrapper> messageWrappers) {
-        Collections.sort(messageWrappers, new Comparator<MessageWrapper>() {
+    private List<StatusMessage> reorderMessages(List<MessageStatusWithPriority> messageWrappers) {
+        Collections.sort(messageWrappers, new Comparator<MessageStatusWithPriority>() {
             @Override
-            public int compare(MessageWrapper msg1, MessageWrapper msg2) {
+            public int compare(MessageStatusWithPriority msg1, MessageStatusWithPriority msg2) {
                 return msg1.mPriority - msg2.mPriority;
             }
         });
-        List<Message> reorderMessages = new ArrayList<VoicemailStatusHelper.Message>();
+        List<StatusMessage> reorderMessages = new ArrayList<VoicemailStatusHelper.StatusMessage>();
         // Copy the ordered message objects into the final list.
-        for (MessageWrapper messageWrapper : messageWrappers) {
+        for (MessageStatusWithPriority messageWrapper : messageWrappers) {
             reorderMessages.add(messageWrapper.mMessage);
         }
         return reorderMessages;
@@ -182,7 +182,7 @@
     /**
      * Returns the message for the status entry pointed to by the cursor.
      */
-    private MessageWrapper getMessageForStatusEntry(Cursor cursor) {
+    private MessageStatusWithPriority getMessageForStatusEntry(Cursor cursor) {
         final String sourcePackage = cursor.getString(SOURCE_PACKAGE_INDEX);
         if (sourcePackage == null) {
             return null;
@@ -203,8 +203,8 @@
         } else if (action == Action.CONFIGURE_VOICEMAIL) {
             actionUri = Uri.parse(cursor.getString(SETTINGS_URI_INDEX));
         }
-        return new MessageWrapper(
-                new Message(sourcePackage, overallState.getMessageId(), action.getMessageId(),
+        return new MessageStatusWithPriority(
+                new StatusMessage(sourcePackage, overallState.getMessageId(), action.getMessageId(),
                         actionUri),
                 overallState.getPriority());
     }
diff --git a/src/com/android/contacts/editor/EventFieldEditorView.java b/src/com/android/contacts/editor/EventFieldEditorView.java
index bf93d26..41d564a 100644
--- a/src/com/android/contacts/editor/EventFieldEditorView.java
+++ b/src/com/android/contacts/editor/EventFieldEditorView.java
@@ -106,6 +106,9 @@
         String data = DateUtils.formatDate(getContext(), getEntry().getAsString(column));
         if (TextUtils.isEmpty(data)) {
             data = " ";
+            setDeleteButtonVisible(false);
+        } else {
+            setDeleteButtonVisible(true);
         }
         mDateView.setText(data);
     }
diff --git a/src/com/android/contacts/editor/KindSectionView.java b/src/com/android/contacts/editor/KindSectionView.java
index b472279..8ca7a05 100644
--- a/src/com/android/contacts/editor/KindSectionView.java
+++ b/src/com/android/contacts/editor/KindSectionView.java
@@ -194,9 +194,9 @@
 
         if (view instanceof Editor) {
             Editor editor = (Editor) view;
+            editor.setDeletable(true);
             editor.setValues(mKind, entry, mState, mReadOnly, mViewIdGenerator);
             editor.setEditorListener(this);
-            editor.setDeletable(true);
         }
         mEditors.addView(view);
         return view;
diff --git a/src/com/android/contacts/editor/LabeledEditorView.java b/src/com/android/contacts/editor/LabeledEditorView.java
index af5ae65..ddecf5a 100644
--- a/src/com/android/contacts/editor/LabeledEditorView.java
+++ b/src/com/android/contacts/editor/LabeledEditorView.java
@@ -73,6 +73,7 @@
     private EntityDelta mState;
     private boolean mReadOnly;
     private boolean mWasEmpty = true;
+    private boolean mIsDeletable = true;
 
     private EditType mType;
 
@@ -185,8 +186,8 @@
     /**
      * Creates or removes the remove button. Doesn't do anything if already correctly configured
      */
-    private void setupDeleteButton(boolean shouldExist) {
-        if (shouldExist) {
+    private void setupDeleteButton() {
+        if (mIsDeletable) {
             mDeleteContainer.setVisibility(View.VISIBLE);
             mDelete.setEnabled(!mReadOnly && isEnabled());
         } else {
@@ -194,6 +195,12 @@
         }
     }
 
+    public void setDeleteButtonVisible(boolean visible) {
+        if (mIsDeletable) {
+            mDeleteContainer.setVisibility(visible ? View.VISIBLE : View.GONE);
+        }
+    }
+
     protected void onOptionalFieldVisibilityChange() {
         if (mListener != null) {
             mListener.onRequest(EditorListener.EDITOR_FORM_CHANGED);
@@ -207,7 +214,8 @@
 
     @Override
     public void setDeletable(boolean deletable) {
-        setupDeleteButton(deletable);
+        mIsDeletable = deletable;
+        setupDeleteButton();
     }
 
     @Override
@@ -267,8 +275,10 @@
         if (mWasEmpty != isEmpty) {
             if (isEmpty) {
                 mListener.onRequest(EditorListener.FIELD_TURNED_EMPTY);
+                if (mIsDeletable) mDeleteContainer.setVisibility(View.GONE);
             } else {
                 mListener.onRequest(EditorListener.FIELD_TURNED_NON_EMPTY);
+                if (mIsDeletable) mDeleteContainer.setVisibility(View.VISIBLE);
             }
             mWasEmpty = isEmpty;
         }
diff --git a/src/com/android/contacts/editor/TextFieldsEditorView.java b/src/com/android/contacts/editor/TextFieldsEditorView.java
index a689a0c..ad1c7b6 100644
--- a/src/com/android/contacts/editor/TextFieldsEditorView.java
+++ b/src/com/android/contacts/editor/TextFieldsEditorView.java
@@ -195,6 +195,9 @@
             final String value = entry.getAsString(column);
             fieldView.setText(value);
 
+            // Show the delete button if we have a non-null value
+            setDeleteButtonVisible(value != null);
+
             // Prepare listener for writing changes
             fieldView.addTextChangedListener(new TextWatcher() {
                 @Override
diff --git a/src/com/android/contacts/group/GroupDetailFragment.java b/src/com/android/contacts/group/GroupDetailFragment.java
index c5f6ef4..7f0536f 100644
--- a/src/com/android/contacts/group/GroupDetailFragment.java
+++ b/src/com/android/contacts/group/GroupDetailFragment.java
@@ -23,6 +23,8 @@
 import com.android.contacts.interactions.GroupDeletionDialogFragment;
 import com.android.contacts.list.ContactTileAdapter;
 import com.android.contacts.list.ContactTileAdapter.DisplayType;
+import com.android.contacts.model.AccountType;
+import com.android.contacts.model.AccountTypeManager;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -90,10 +92,12 @@
 
     private ContactTileAdapter mAdapter;
     private ContactPhotoManager mPhotoManager;
+    private AccountTypeManager mAccountTypeManager;
 
     private Uri mGroupUri;
     private long mGroupId;
     private String mGroupName;
+    private String mAccountTypeString;
 
     private boolean mOptionsMenuEditable;
     private boolean mCloseActivityAfterDelete;
@@ -105,6 +109,7 @@
     public void onAttach(Activity activity) {
         super.onAttach(activity);
         mContext = activity;
+        mAccountTypeManager = AccountTypeManager.getInstance(mContext);
 
         Resources res = getResources();
         int columnCount = res.getInteger(R.integer.contact_tile_column_count);
@@ -214,7 +219,7 @@
                     return;
                 }
             }
-            updateSize(null);
+            updateSize(-1);
             updateTitle(null);
         }
 
@@ -235,7 +240,7 @@
 
         @Override
         public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
-            updateSize(Integer.toString(data.getCount()));
+            updateSize(data.getCount());
             mAdapter.loadFromCursor(data);
         }
 
@@ -246,6 +251,7 @@
     private void bindGroupMetaData(Cursor cursor) {
         cursor.moveToPosition(-1);
         if (cursor.moveToNext()) {
+            mAccountTypeString = cursor.getString(GroupMetaDataLoader.ACCOUNT_TYPE);
             mGroupId = cursor.getLong(GroupMetaDataLoader.GROUP_ID);
             mGroupName = cursor.getString(GroupMetaDataLoader.TITLE);
             updateTitle(mGroupName);
@@ -265,11 +271,26 @@
         }
     }
 
-    private void updateSize(String size) {
-        if (mGroupSize != null) {
-            mGroupSize.setText(size);
+    /**
+     * Display the count of the number of group members.
+     * @param size of the group (can be -1 if no size could be determined)
+     */
+    private void updateSize(int size) {
+        String groupSizeString;
+        if (size == -1) {
+            groupSizeString = null;
         } else {
-            mListener.onGroupSizeUpdated(size);
+            String groupSizeTemplateString = getResources().getQuantityString(
+                    R.plurals.num_contacts_in_group, size);
+            AccountType accountType = mAccountTypeManager.getAccountType(mAccountTypeString);
+            groupSizeString = String.format(groupSizeTemplateString, size,
+                    accountType.getDisplayLabel(mContext));
+        }
+
+        if (mGroupSize != null) {
+            mGroupSize.setText(groupSizeString);
+        } else {
+            mListener.onGroupSizeUpdated(groupSizeString);
         }
     }
 
diff --git a/src/com/android/contacts/list/ContactsRequest.java b/src/com/android/contacts/list/ContactsRequest.java
index 469cd1d..b7e21b4 100644
--- a/src/com/android/contacts/list/ContactsRequest.java
+++ b/src/com/android/contacts/list/ContactsRequest.java
@@ -89,6 +89,22 @@
     private boolean mDirectorySearchEnabled = true;
     private Uri mContactUri;
 
+    @Override
+    public String toString() {
+        return "{ContactsRequest:mValid=" + mValid
+                + " mActionCode=" + mActionCode
+                + " mRedirectIntent=" + mRedirectIntent
+                + " mTitle=" + mTitle
+                + " mSearchMode=" + mSearchMode
+                + " mQueryString=" + mQueryString
+                + " mIncludeProfile=" + mIncludeProfile
+                + " mGroupName=" + mGroupName
+                + " mLegacyCompatibilityMode=" + mLegacyCompatibilityMode
+                + " mDirectorySearchEnabled=" + mDirectorySearchEnabled
+                + " mContactUri=" + mContactUri
+                + "}";
+    }
+
     /**
      * Copies all fields.
      */
diff --git a/tests/src/com/android/contacts/activities/CallLogActivityTests.java b/tests/src/com/android/contacts/activities/CallLogActivityTests.java
index dfb6d0c..8900c5e 100644
--- a/tests/src/com/android/contacts/activities/CallLogActivityTests.java
+++ b/tests/src/com/android/contacts/activities/CallLogActivityTests.java
@@ -26,6 +26,7 @@
 import android.database.MatrixCursor;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
+import android.net.Uri;
 import android.provider.CallLog.Calls;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.telephony.PhoneNumberUtils;
@@ -69,8 +70,8 @@
 
     /** A test value for the person id of a contact. */
     private static final long TEST_PERSON_ID = 1;
-    /** A test value for the photo id of a contact. */
-    private static final long TEST_PHOTO_ID = 2;
+    /** A test value for the photo uri of a contact. */
+    private static final Uri TEST_THUMBNAIL_URI = Uri.parse("something://picture/2");
     /** A test value for the lookup key for contacts. */
     private static final String TEST_LOOKUP_KEY = "contact_id";
     /** A test value for the country ISO of the phone number in the call log. */
@@ -177,7 +178,6 @@
         View view = mAdapter.newStandAloneView(getActivity(), mParentView);
         mAdapter.bindStandAloneView(view, getActivity(), mCursor);
         assertNotNull(view.findViewById(R.id.call_icon));
-        assertNull(view.findViewById(R.id.groupIndicator));
     }
 
     @MediumTest
@@ -187,7 +187,6 @@
         View view = mAdapter.newChildView(getActivity(), mParentView);
         mAdapter.bindChildView(view, getActivity(), mCursor);
         assertNotNull(view.findViewById(R.id.call_icon));
-        assertNull(view.findViewById(R.id.groupIndicator));
     }
 
     @MediumTest
@@ -400,7 +399,7 @@
         }
         contactInfo.formattedNumber = formattedNumber;
         contactInfo.normalizedNumber = number;
-        contactInfo.photoId = TEST_PHOTO_ID;
+        contactInfo.thumbnailUri = TEST_THUMBNAIL_URI;
         contactInfo.lookupKey = TEST_LOOKUP_KEY;
         mAdapter.injectContactInfoForTest(number, contactInfo);
     }
diff --git a/tests/src/com/android/contacts/calllog/VoicemailStatusHelperImplTest.java b/tests/src/com/android/contacts/calllog/VoicemailStatusHelperImplTest.java
index d577d4c..c6bff13 100644
--- a/tests/src/com/android/contacts/calllog/VoicemailStatusHelperImplTest.java
+++ b/tests/src/com/android/contacts/calllog/VoicemailStatusHelperImplTest.java
@@ -28,7 +28,7 @@
 import static android.provider.VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_OK;
 
 import com.android.contacts.R;
-import com.android.contacts.calllog.VoicemailStatusHelper.Message;
+import com.android.contacts.calllog.VoicemailStatusHelper.StatusMessage;
 
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -50,7 +50,8 @@
     private static final Uri TEST_SETTINGS_URI = Uri.parse("http://www.visual.voicemail.setup");
     private static final Uri TEST_VOICEMAIL_URI = Uri.parse("tel:901");
 
-    private static final int ACTION_MSG_CALL_VOICEMAIL = R.string.voicemail_status_action_call_server;
+    private static final int ACTION_MSG_CALL_VOICEMAIL =
+            R.string.voicemail_status_action_call_server;
     private static final int ACTION_MSG_CONFIGURE = R.string.voicemail_status_action_configure;
 
     private static final int STATUS_MSG_VOICEMAIL_NOT_AVAILABLE =
@@ -166,7 +167,7 @@
         // package2 with  valuesNoNotificationNoDataChannel. Package2 should be above.
         updateEntryForPackage(TEST_PACKAGE_1, valuesNoNotificationGoodDataChannel);
         updateEntryForPackage(TEST_PACKAGE_2, valuesNoNotificationNoDataChannel);
-        List<Message> messages = mStatusHelper.getStatusMessages();
+        List<StatusMessage> messages = mStatusHelper.getStatusMessages();
         assertEquals(2, messages.size());
         assertEquals(TEST_PACKAGE_1, messages.get(1).sourcePackage);
         assertEquals(TEST_PACKAGE_2, messages.get(0).sourcePackage);
@@ -189,13 +190,13 @@
 
     private void checkExpectedMessage(String sourcePackage, ContentValues values,
             int expectedStatusMsg, int expectedActionMsg, Uri expectedUri) {
-        List<Message> messages = mStatusHelper.getStatusMessages();
+        List<StatusMessage> messages = mStatusHelper.getStatusMessages();
         assertEquals(1, messages.size());
         checkMessageMatches(messages.get(0), sourcePackage, expectedStatusMsg, expectedActionMsg,
                 expectedUri);
     }
 
-    private void checkMessageMatches(Message message, String expectedSourcePackage,
+    private void checkMessageMatches(StatusMessage message, String expectedSourcePackage,
             int expectedStatusMsg, int expectedActionMsg, Uri expectedUri) {
         assertEquals(expectedSourcePackage, message.sourcePackage);
         assertEquals(expectedStatusMsg, message.statusMessageId);
@@ -209,7 +210,7 @@
 
     private void checkNoMessages(String sourcePackage, ContentValues values) {
         assertEquals(1, updateEntryForPackage(sourcePackage, values));
-        List<Message> messages = mStatusHelper.getStatusMessages();
+        List<StatusMessage> messages = mStatusHelper.getStatusMessages();
         assertEquals(0, messages.size());
     }