Merge "Stream items UI."
diff --git a/res/drawable-hdpi/btn_call_pressed.png b/res/drawable-hdpi/btn_call_pressed.png
index f4b7bef..6b497a2 100644
--- a/res/drawable-hdpi/btn_call_pressed.png
+++ b/res/drawable-hdpi/btn_call_pressed.png
Binary files differ
diff --git a/res/drawable-hdpi/btn_dial_pressed.png b/res/drawable-hdpi/btn_dial_pressed.png
index 5ae0b16..9c73cca 100644
--- a/res/drawable-hdpi/btn_dial_pressed.png
+++ b/res/drawable-hdpi/btn_dial_pressed.png
Binary files differ
diff --git a/res/drawable-hdpi/btn_dial_textfield_activated.9.png b/res/drawable-hdpi/btn_dial_textfield_activated.9.png
deleted file mode 100644
index d30e51d..0000000
--- a/res/drawable-hdpi/btn_dial_textfield_activated.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/dial_background_texture.png b/res/drawable-hdpi/dial_background_texture.png
index 177fad8..5b299fd 100644
--- a/res/drawable-hdpi/dial_background_texture.png
+++ b/res/drawable-hdpi/dial_background_texture.png
Binary files differ
diff --git a/res/drawable-hdpi/dial_num_0_wht.png b/res/drawable-hdpi/dial_num_0_wht.png
index b7672e0..a0720f3 100644
--- a/res/drawable-hdpi/dial_num_0_wht.png
+++ b/res/drawable-hdpi/dial_num_0_wht.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_dial_action_call.png b/res/drawable-hdpi/ic_dial_action_call.png
index b4bdbd5..ed08eb8 100644
--- a/res/drawable-hdpi/ic_dial_action_call.png
+++ b/res/drawable-hdpi/ic_dial_action_call.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_dial_action_delete.png b/res/drawable-hdpi/ic_dial_action_delete.png
index 13ecb30..f93a308 100644
--- a/res/drawable-hdpi/ic_dial_action_delete.png
+++ b/res/drawable-hdpi/ic_dial_action_delete.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_dial_action_search.png b/res/drawable-hdpi/ic_dial_action_search.png
index 48000df..898ce11 100644
--- a/res/drawable-hdpi/ic_dial_action_search.png
+++ b/res/drawable-hdpi/ic_dial_action_search.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_overflow.png b/res/drawable-hdpi/ic_menu_overflow.png
index 84ac9ea..b028095 100644
--- a/res/drawable-hdpi/ic_menu_overflow.png
+++ b/res/drawable-hdpi/ic_menu_overflow.png
Binary files differ
diff --git a/res/drawable-mdpi/btn_call_pressed.png b/res/drawable-mdpi/btn_call_pressed.png
index b5c49de..637b06a 100644
--- a/res/drawable-mdpi/btn_call_pressed.png
+++ b/res/drawable-mdpi/btn_call_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/btn_dial_pressed.png b/res/drawable-mdpi/btn_dial_pressed.png
index a39a2ba..2440553 100644
--- a/res/drawable-mdpi/btn_dial_pressed.png
+++ b/res/drawable-mdpi/btn_dial_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/btn_dial_textfield_activated.9.png b/res/drawable-mdpi/btn_dial_textfield_activated.9.png
deleted file mode 100644
index 4481a68..0000000
--- a/res/drawable-mdpi/btn_dial_textfield_activated.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/change_photo_box_focused_holo_light.9.png b/res/drawable-mdpi/change_photo_box_focused_holo_light.9.png
index 36c8b87..47fb773 100644
--- a/res/drawable-mdpi/change_photo_box_focused_holo_light.9.png
+++ b/res/drawable-mdpi/change_photo_box_focused_holo_light.9.png
Binary files differ
diff --git a/res/drawable-mdpi/change_photo_box_normal_holo_light.9.png b/res/drawable-mdpi/change_photo_box_normal_holo_light.9.png
index d380b40..591e6d5 100644
--- a/res/drawable-mdpi/change_photo_box_normal_holo_light.9.png
+++ b/res/drawable-mdpi/change_photo_box_normal_holo_light.9.png
Binary files differ
diff --git a/res/drawable-mdpi/change_photo_box_pressed_holo_light.9.png b/res/drawable-mdpi/change_photo_box_pressed_holo_light.9.png
index 21d8a96..5d5eee2 100644
--- a/res/drawable-mdpi/change_photo_box_pressed_holo_light.9.png
+++ b/res/drawable-mdpi/change_photo_box_pressed_holo_light.9.png
Binary files differ
diff --git a/res/drawable-mdpi/dial_background_texture.png b/res/drawable-mdpi/dial_background_texture.png
index de6b72a..881f3a0 100644
--- a/res/drawable-mdpi/dial_background_texture.png
+++ b/res/drawable-mdpi/dial_background_texture.png
Binary files differ
diff --git a/res/drawable-mdpi/dial_num_0_wht.png b/res/drawable-mdpi/dial_num_0_wht.png
index eff8c59..5391fb3 100644
--- a/res/drawable-mdpi/dial_num_0_wht.png
+++ b/res/drawable-mdpi/dial_num_0_wht.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_dial_action_call.png b/res/drawable-mdpi/ic_dial_action_call.png
index 35f8fbf..59a68f2 100644
--- a/res/drawable-mdpi/ic_dial_action_call.png
+++ b/res/drawable-mdpi/ic_dial_action_call.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_dial_action_delete.png b/res/drawable-mdpi/ic_dial_action_delete.png
index edbcfd0..32b0022 100644
--- a/res/drawable-mdpi/ic_dial_action_delete.png
+++ b/res/drawable-mdpi/ic_dial_action_delete.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_dial_action_search.png b/res/drawable-mdpi/ic_dial_action_search.png
index a700ce4..88cba92 100644
--- a/res/drawable-mdpi/ic_dial_action_search.png
+++ b/res/drawable-mdpi/ic_dial_action_search.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_overflow.png b/res/drawable-mdpi/ic_menu_overflow.png
index bc2ea5e..74dd41a 100644
--- a/res/drawable-mdpi/ic_menu_overflow.png
+++ b/res/drawable-mdpi/ic_menu_overflow.png
Binary files differ
diff --git a/res/drawable-xhdpi/btn_call_pressed.png b/res/drawable-xhdpi/btn_call_pressed.png
index 17e397b..cdf52f8 100644
--- a/res/drawable-xhdpi/btn_call_pressed.png
+++ b/res/drawable-xhdpi/btn_call_pressed.png
Binary files differ
diff --git a/res/drawable-xhdpi/btn_dial_pressed.png b/res/drawable-xhdpi/btn_dial_pressed.png
index fe0bfe9..27c95b7 100644
--- a/res/drawable-xhdpi/btn_dial_pressed.png
+++ b/res/drawable-xhdpi/btn_dial_pressed.png
Binary files differ
diff --git a/res/drawable-xhdpi/btn_dial_textfield_activated.9.png b/res/drawable-xhdpi/btn_dial_textfield_activated.9.png
deleted file mode 100644
index 9c5e4f4..0000000
--- a/res/drawable-xhdpi/btn_dial_textfield_activated.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/dial_background_texture.png b/res/drawable-xhdpi/dial_background_texture.png
index 2318e54..4c8617a 100644
--- a/res/drawable-xhdpi/dial_background_texture.png
+++ b/res/drawable-xhdpi/dial_background_texture.png
Binary files differ
diff --git a/res/drawable-xhdpi/dial_num_0_wht.png b/res/drawable-xhdpi/dial_num_0_wht.png
index 16b2935..99aca70 100644
--- a/res/drawable-xhdpi/dial_num_0_wht.png
+++ b/res/drawable-xhdpi/dial_num_0_wht.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_dial_action_call.png b/res/drawable-xhdpi/ic_dial_action_call.png
index ec0b482..0bd9803 100644
--- a/res/drawable-xhdpi/ic_dial_action_call.png
+++ b/res/drawable-xhdpi/ic_dial_action_call.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_dial_action_delete.png b/res/drawable-xhdpi/ic_dial_action_delete.png
index 9505f9d..9c0b4f0 100644
--- a/res/drawable-xhdpi/ic_dial_action_delete.png
+++ b/res/drawable-xhdpi/ic_dial_action_delete.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_dial_action_search.png b/res/drawable-xhdpi/ic_dial_action_search.png
index ce9ad6e..fe3aa24 100644
--- a/res/drawable-xhdpi/ic_dial_action_search.png
+++ b/res/drawable-xhdpi/ic_dial_action_search.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_menu_overflow.png b/res/drawable-xhdpi/ic_menu_overflow.png
index 0abd760..c88c4a4 100644
--- a/res/drawable-xhdpi/ic_menu_overflow.png
+++ b/res/drawable-xhdpi/ic_menu_overflow.png
Binary files differ
diff --git a/res/drawable/attachment_button.png b/res/drawable/attachment_button.png
deleted file mode 100644
index 3020e6e..0000000
--- a/res/drawable/attachment_button.png
+++ /dev/null
Binary files differ
diff --git a/res/layout-sw580dp/event_field_editor_view.xml b/res/layout-sw580dp/event_field_editor_view.xml
index c9eef08..f31b283 100644
--- a/res/layout-sw580dp/event_field_editor_view.xml
+++ b/res/layout-sw580dp/event_field_editor_view.xml
@@ -23,10 +23,6 @@
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:orientation="vertical">
 
-    <include
-        android:id="@+id/title"
-        layout="@layout/edit_field_title" />
-
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/res/layout-sw580dp/item_kind_section.xml b/res/layout-sw580dp/item_kind_section.xml
index dd38e26..5ff2da2 100644
--- a/res/layout-sw580dp/item_kind_section.xml
+++ b/res/layout-sw580dp/item_kind_section.xml
@@ -22,11 +22,10 @@
     android:layout_height="wrap_content"
     android:paddingBottom="@dimen/editor_field_bottom_padding"
     android:orientation="vertical">
-    <ImageView
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:scaleType="fitXY"
-        android:src="@drawable/divider_horizontal_light" />
+
+    <include
+        android:id="@+id/kind_title_layout"
+        layout="@layout/edit_kind_title" />
 
     <LinearLayout
         android:id="@+id/kind_editors"
diff --git a/res/layout-sw580dp/text_fields_editor_view.xml b/res/layout-sw580dp/text_fields_editor_view.xml
index 8be354b..be0ea67 100644
--- a/res/layout-sw580dp/text_fields_editor_view.xml
+++ b/res/layout-sw580dp/text_fields_editor_view.xml
@@ -21,10 +21,6 @@
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:orientation="vertical">
 
-    <include
-        android:id="@+id/title"
-        layout="@layout/edit_field_title" />
-
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/res/layout/contact_detail_list_item.xml b/res/layout/contact_detail_list_item.xml
index a116cb3..2ea8425 100644
--- a/res/layout/contact_detail_list_item.xml
+++ b/res/layout/contact_detail_list_item.xml
@@ -21,10 +21,6 @@
     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:paddingTop="@dimen/detail_item_vertical_margin"
-    android:paddingBottom="@dimen/detail_item_vertical_margin"
     android:orientation="horizontal"
     android:gravity="center_vertical">
 
diff --git a/res/layout/contact_detail_network_title_entry_view.xml b/res/layout/contact_detail_network_title_entry_view.xml
new file mode 100644
index 0000000..2cede93
--- /dev/null
+++ b/res/layout/contact_detail_network_title_entry_view.xml
@@ -0,0 +1,46 @@
+<?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:paddingTop="@dimen/detail_item_vertical_margin"
+    android:paddingBottom="@dimen/detail_item_vertical_margin"
+    android:orientation="horizontal"
+    android:gravity="center_vertical">
+
+    <ImageView
+        android:id="@+id/network_icon"
+        android:layout_width="@dimen/detail_network_icon_size"
+        android:layout_height="@dimen/detail_network_icon_size"
+        android:layout_gravity="center_vertical"
+        android:scaleType="centerInside" />
+
+    <TextView
+        android:id="@+id/network_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="@dimen/detail_item_side_margin"
+        android:layout_gravity="center_vertical"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+
+</LinearLayout>
diff --git a/res/layout/contact_detail_separator_entry_view.xml b/res/layout/contact_detail_separator_entry_view.xml
index abdca5f..abe1cf8 100644
--- a/res/layout/contact_detail_separator_entry_view.xml
+++ b/res/layout/contact_detail_separator_entry_view.xml
@@ -16,9 +16,7 @@
 
 <FrameLayout 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:layout_height="wrap_content">
 
     <View
       android:layout_width="match_parent"
diff --git a/res/layout/contact_editor_custom_action_bar.xml b/res/layout/contact_editor_custom_action_bar.xml
new file mode 100644
index 0000000..ba09929
--- /dev/null
+++ b/res/layout/contact_editor_custom_action_bar.xml
@@ -0,0 +1,59 @@
+<?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.
+-->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout
+        android:id="@+id/save_menu_item"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:divider="?android:attr/dividerVertical"
+        android:showDividers="end"
+        android:dividerPadding="12dip"
+        android:orientation="horizontal"
+        style="?android:attr/actionButtonStyle">
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:orientation="horizontal">
+
+            <ImageView
+                android:id="@+id/icon"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical"
+                android:layout_marginRight="8dip"
+                android:src="@drawable/ic_menu_done_holo_light"
+                android:description="@string/menu_done" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical"
+                android:layout_marginRight="20dip"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:text="@string/menu_done"
+                style="@android:style/Widget.Holo.ActionBar.TabText" />
+
+        </LinearLayout>
+
+    </LinearLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/edit_add_field.xml b/res/layout/edit_add_field.xml
index 1c8c740..f6bc631 100644
--- a/res/layout/edit_add_field.xml
+++ b/res/layout/edit_add_field.xml
@@ -14,8 +14,7 @@
      limitations under the License.
 -->
 <!-- Layout of "add field" row in contact editor -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="horizontal"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:paddingLeft="13dip"
@@ -23,17 +22,9 @@
     <TextView
         android:id="@+id/add_text"
         android:layout_gravity="center_vertical"
-        android:layout_width="0dip"
-        android:layout_weight="1"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:textAppearance="?android:attr/textAppearanceSmall"
+        android:duplicateParentState="true"
+        android:textAppearance="?android:attr/textAppearanceMedium"
         android:textColor="?android:attr/textColorTertiary" />
-    <ImageView
-        android:id="@+id/add_button"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:src="@drawable/ic_menu_add_field_holo_light"
-        android:paddingLeft="@dimen/editor_round_button_padding_left"
-        android:paddingRight="@dimen/editor_round_button_padding_right"
-        android:contentDescription="@string/description_plus_button" />
-</LinearLayout>
\ No newline at end of file
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/edit_field_list.xml b/res/layout/edit_field_list.xml
index f9e6565..ba715c7 100644
--- a/res/layout/edit_field_list.xml
+++ b/res/layout/edit_field_list.xml
@@ -23,5 +23,4 @@
     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/layout/edit_field_title.xml b/res/layout/edit_field_title.xml
deleted file mode 100644
index 4918c4d..0000000
--- a/res/layout/edit_field_title.xml
+++ /dev/null
@@ -1,29 +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.
--->
-
-<!-- Title of a field in the contact editor. -->
-
-<TextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/title"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:paddingTop="@dimen/editor_field_top_padding"
-    android:paddingLeft="@dimen/editor_field_left_padding"
-    android:textAppearance="?android:attr/textAppearanceMedium"
-    android:singleLine="true"
-    android:ellipsize="marquee"
-    android:fadingEdge="horizontal" />
\ No newline at end of file
diff --git a/res/layout/edit_kind_title.xml b/res/layout/edit_kind_title.xml
new file mode 100644
index 0000000..619ba49
--- /dev/null
+++ b/res/layout/edit_kind_title.xml
@@ -0,0 +1,48 @@
+<?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/editor_field_left_padding"
+    android:paddingRight="@dimen/editor_field_right_padding"
+    android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/kind_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingLeft="@dimen/editor_field_left_padding"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textColor="@color/people_app_theme_color"
+        android:textStyle="bold"
+        android:singleLine="true"
+        android:ellipsize="end"
+        android:paddingTop="5dip"
+        android:paddingBottom="2dip" />
+
+    <ImageView
+        android:id="@+id/divider"
+        android:layout_width="match_parent"
+        android:layout_height="2dip"
+        android:scaleType="fitXY"
+        android:src="@color/people_app_theme_color"/>
+
+</LinearLayout>
diff --git a/res/layout/edit_spinner.xml b/res/layout/edit_spinner.xml
index 9e22ee7..325eb50 100644
--- a/res/layout/edit_spinner.xml
+++ b/res/layout/edit_spinner.xml
@@ -16,11 +16,12 @@
 
 <!-- Spinner for a field in the contact editor. -->
 
+<!-- Note: explicitly override the default left and right padding on spinner -->
 <Spinner
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/spinner"
-    android:layout_width="wrap_content"
+    android:layout_width="@dimen/editor_type_label_width"
     android:layout_height="wrap_content"
-    android:layout_marginLeft="@dimen/editor_field_left_padding"
-    android:textAppearance="?android:attr/textAppearanceLarge"
-    android:paddingLeft="5dip"/>
\ No newline at end of file
+    android:paddingLeft="5dip"
+    android:paddingRight="20dip"
+    android:textAppearance="?android:attr/textAppearanceSmall"/>
\ No newline at end of file
diff --git a/res/layout/event_field_editor_view.xml b/res/layout/event_field_editor_view.xml
index 6625279..0dceafc 100644
--- a/res/layout/event_field_editor_view.xml
+++ b/res/layout/event_field_editor_view.xml
@@ -22,15 +22,6 @@
     android:layout_height="wrap_content"
     android:orientation="vertical">
 
-    <include
-        android:id="@+id/title"
-        layout="@layout/edit_field_title" />
-
-    <include
-        android:id="@+id/spinner"
-        layout="@layout/edit_spinner"
-        android:visibility="gone" />
-
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
@@ -45,6 +36,11 @@
             layout="@layout/edit_date_picker" />
 
         <include
+            android:id="@+id/spinner"
+            layout="@layout/edit_spinner"
+            android:visibility="gone" />
+
+        <include
             android:id="@+id/delete_button_container"
             layout="@layout/edit_delete_button"
             android:visibility="gone" />
diff --git a/res/layout/item_group_membership.xml b/res/layout/item_group_membership.xml
index 13ddb20..62d06ea 100644
--- a/res/layout/item_group_membership.xml
+++ b/res/layout/item_group_membership.xml
@@ -20,15 +20,8 @@
     android:layout_height="wrap_content"
     android:orientation="vertical">
 
-    <ImageView
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:scaleType="fitXY"
-        android:src="@drawable/divider_horizontal_light" />
-
     <include
-        android:id="@+id/kind_title"
-        layout="@layout/edit_field_title" />
+        layout="@layout/edit_kind_title" />
 
     <Button
         style="?android:attr/spinnerStyle"
@@ -41,7 +34,6 @@
         android:gravity="left|center_vertical"
         android:ellipsize="end"
         android:focusable="true"
-        android:paddingLeft="@dimen/editor_field_left_padding"
-    />
+        android:paddingLeft="@dimen/editor_field_left_padding" />
 
 </com.android.contacts.editor.GroupMembershipView>
diff --git a/res/layout/item_kind_section.xml b/res/layout/item_kind_section.xml
index 2c6dc6f..0b6017c 100644
--- a/res/layout/item_kind_section.xml
+++ b/res/layout/item_kind_section.xml
@@ -23,11 +23,9 @@
     android:paddingBottom="@dimen/editor_field_bottom_padding"
     android:orientation="vertical">
 
-    <ImageView
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:scaleType="fitXY"
-        android:src="@drawable/divider_horizontal_light" />
+    <include
+        android:id="@+id/kind_title_layout"
+        layout="@layout/edit_kind_title" />
 
     <LinearLayout
         android:id="@+id/kind_editors"
diff --git a/res/layout/organization_editor_view_switcher.xml b/res/layout/organization_editor_view_switcher.xml
new file mode 100644
index 0000000..c6e16ae
--- /dev/null
+++ b/res/layout/organization_editor_view_switcher.xml
@@ -0,0 +1,45 @@
+<?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.
+-->
+
+<!--
+  Layout of "organization" field in contact editor which either shows the "add
+  organization" button or a container (which should be populated with the actual
+  list of edit text fields).
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingLeft="@dimen/editor_field_left_padding"
+    android:paddingRight="@dimen/editor_field_right_padding"
+    android:background="?android:attr/selectableItemBackground">
+
+    <TextView
+        android:id="@+id/add_organization_button"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingLeft="@dimen/editor_field_left_padding"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:text="@string/organizationLabelsGroup"
+        android:duplicateParentState="true"/>
+
+    <FrameLayout
+        android:id="@+id/container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:visibility="gone"/>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/raw_contact_editor_view.xml b/res/layout/raw_contact_editor_view.xml
index 2f62fe0..79183cd 100644
--- a/res/layout/raw_contact_editor_view.xml
+++ b/res/layout/raw_contact_editor_view.xml
@@ -44,8 +44,7 @@
                 android:id="@+id/account_type"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:textSize="20sp"
-                android:textColor="?android:attr/textColorPrimary"
+                android:textAppearance="?android:attr/textAppearanceMedium"
                 android:singleLine="true" />
 
             <TextView
@@ -53,17 +52,24 @@
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:textAppearance="?android:attr/textAppearanceSmall"
-                 android:textColor="?android:attr/textColorPrimary"
+                 android:textColor="?android:attr/textColorTertiary"
                  android:singleLine="true" />
 
         </LinearLayout>
 
-        <ImageView
-             android:id="@+id/account_icon"
-             android:layout_width="wrap_content"
-             android:layout_height="wrap_content"
-             android:layout_marginLeft="7dip"
-             android:layout_marginRight="7dip" />
+        <FrameLayout
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent">
+
+            <ImageView
+                 android:id="@+id/account_icon"
+                 android:layout_width="32dip"
+                 android:layout_height="32dip"
+                 android:layout_marginLeft="24dip"
+                 android:layout_marginRight="24dip"
+                 android:layout_gravity="center_vertical" />
+
+        </FrameLayout>
 
     </LinearLayout>
 
@@ -86,7 +92,8 @@
             <FrameLayout
                 android:id="@+id/stub_photo"
                 android:layout_width="wrap_content"
-                android:layout_height="wrap_content">
+                android:layout_height="wrap_content"
+                android:layout_marginRight="16dip">
 
                 <include
                     android:id="@+id/edit_photo"
diff --git a/res/layout/text_fields_editor_view.xml b/res/layout/text_fields_editor_view.xml
index d33e804..c8d35a4 100644
--- a/res/layout/text_fields_editor_view.xml
+++ b/res/layout/text_fields_editor_view.xml
@@ -20,15 +20,6 @@
     android:layout_height="wrap_content"
     android:orientation="vertical">
 
-    <include
-        android:id="@+id/title"
-        layout="@layout/edit_field_title" />
-
-    <include
-        android:id="@+id/spinner"
-        layout="@layout/edit_spinner"
-        android:visibility="gone" />
-
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
@@ -43,6 +34,11 @@
             layout="@layout/edit_field_list" />
 
         <include
+            android:id="@+id/spinner"
+            layout="@layout/edit_spinner"
+            android:visibility="gone" />
+
+        <include
             android:id="@+id/expansion_view_container"
             layout="@layout/edit_expansion_view"
             android:visibility="gone" />
diff --git a/res/menu/call_log_options.xml b/res/menu/call_log_options.xml
index 1f8de57..0d14f2f 100644
--- a/res/menu/call_log_options.xml
+++ b/res/menu/call_log_options.xml
@@ -21,6 +21,11 @@
         android:showAsAction="withText" />
 
     <item
+        android:id="@+id/show_voicemails_only"
+        android:title="@string/menu_show_voicemails_only"
+        android:showAsAction="withText" />
+
+    <item
         android:id="@+id/menu_call_settings_call_log"
         android:title="@string/call_settings"
         android:showAsAction="withText" />
diff --git a/res/menu/edit_contact.xml b/res/menu/edit_contact.xml
index 857c9c5..26b89df 100644
--- a/res/menu/edit_contact.xml
+++ b/res/menu/edit_contact.xml
@@ -18,20 +18,7 @@
     <item
         android:id="@+id/menu_done"
         android:alphabeticShortcut="\n"
-        android:icon="@drawable/ic_menu_done_holo_light"
-        android:title="@string/menu_done"
-        android:showAsAction="always|withText" />
-
-    <item
-        android:id="@+id/menu_discard"
-        android:alphabeticShortcut="q"
-        android:title="@string/menu_doNotSave"
-        android:showAsAction="always|withText" />
-
-    <item
-        android:id="@+id/menu_delete"
-        android:icon="@drawable/ic_menu_trash_holo_light"
-        android:title="@string/menu_deleteContact" />
+        android:showAsAction="always" />
 
     <item
         android:id="@+id/menu_split"
@@ -42,4 +29,9 @@
         android:id="@+id/menu_join"
         android:icon="@drawable/ic_menu_merge_holo_light"
         android:title="@string/menu_joinAggregate" />
+
+    <item
+        android:id="@+id/menu_discard"
+        android:alphabeticShortcut="q"
+        android:title="@string/menu_discard" />
 </menu>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 71eb9ac..8d19a3e 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <resources>
-    <dimen name="edit_photo_size">90dip</dimen>
+    <dimen name="edit_photo_size">42dip</dimen>
 
     <!-- The height of the ScrollingTabWidget -->
     <dimen name="tab_height">40dip</dimen>
@@ -45,7 +45,7 @@
     <dimen name="editor_round_button_padding_bottom">8dip</dimen>
 
     <!-- Width of the Type-Label in the Editor -->
-    <dimen name="editor_type_label_width">120dip</dimen>
+    <dimen name="editor_type_label_width">100dip</dimen>
 
     <!-- Left padding of a field in the Editor -->
     <dimen name="editor_field_left_padding">5dip</dimen>
@@ -140,6 +140,9 @@
     <!-- Width of a contact detail item type (i.e. Nickname or Website). -->
     <dimen name="detail_item_type_width">164dip</dimen>
 
+    <!-- Width of height of an icon from a third-party app in the networks section of the contact card. -->
+    <dimen name="detail_network_icon_size">32dip</dimen>
+
     <!-- Font size for the display name in header of the contact detail page -->
     <dimen name="detail_header_name_text_size">30sp</dimen>
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 99a1561..87307ae 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -200,9 +200,12 @@
     <!-- Menu item to indicate you are done editing a contact and want to save the changes you've made -->
     <string name="menu_done">Done</string>
 
-    <!-- Menu item to indicate you want to stop editing a contact and NOT save the changes you've made [CHAR LIMIT=12] -->
+    <!-- Menu item to indicate you want to stop editing a group and NOT save the changes you've made [CHAR LIMIT=12] -->
     <string name="menu_doNotSave">Cancel</string>
 
+    <!-- Menu item to indicate you want to stop editing a contact and NOT save the changes you've made [CHAR LIMIT=12] -->
+    <string name="menu_discard">Discard</string>
+
     <!-- The title of the activity that edits and existing contact -->
     <string name="editContact_title_edit">Edit contact</string>
 
@@ -1665,4 +1668,7 @@
 
     <!-- The "file name" displayed for vCards received directly via NFC [CHAR LIMIT=16] -->
     <string name="nfc_vcard_file_name">Contact received over NFC</string>
+
+    <!-- Menu item used to show only voicemails in the call log. [CHAR LIMIT=30] -->
+    <string name="menu_show_voicemails_only">Show voicemails only</string>
 </resources>
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index 14fec85..324ab20 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -169,7 +169,6 @@
         });
     }
 
-
     @Override
     public void onResume() {
         super.onResume();
@@ -184,24 +183,31 @@
      * playback.  If it doesn't, then hide the voicemail ui.
      */
     private void optionallyHandleVoicemail() {
-        Uri voicemailUri = getIntent().getParcelableExtra(EXTRA_VOICEMAIL_URI);
-        FragmentManager manager = getFragmentManager();
-        VoicemailPlaybackFragment fragment = (VoicemailPlaybackFragment) manager.findFragmentById(
-                R.id.voicemail_playback_fragment);
-        if (voicemailUri != null) {
-            // Has voicemail uri: leave the fragment visible.  Optionally start the playback.
+        if (hasVoicemail()) {
+            // Has voicemail: leave the fragment visible.  Optionally start the playback.
             // Do a query to fetch the voicemail status messages.
             boolean startPlayback = getIntent().getBooleanExtra(
                     EXTRA_VOICEMAIL_START_PLAYBACK, false);
-            fragment.setVoicemailUri(voicemailUri, startPlayback);
+            Uri voicemailUri = getIntent().getParcelableExtra(EXTRA_VOICEMAIL_URI);
+            getVoicemailPlaybackFragment().setVoicemailUri(voicemailUri, startPlayback);
             mAsyncQueryHandler.startVoicemailStatusQuery(voicemailUri);
         } else {
             // No voicemail uri: hide the voicemail fragment and the status view.
-            manager.beginTransaction().hide(fragment).commit();
+            getFragmentManager().beginTransaction().hide(getVoicemailPlaybackFragment()).commit();
             mStatusMessageView.setVisibility(View.GONE);
         }
     }
 
+    private boolean hasVoicemail() {
+        return getIntent().getParcelableExtra(EXTRA_VOICEMAIL_URI) != null;
+    }
+
+    private VoicemailPlaybackFragment getVoicemailPlaybackFragment() {
+        FragmentManager manager = getFragmentManager();
+        return (VoicemailPlaybackFragment) manager.findFragmentById(
+                R.id.voicemail_playback_fragment);
+    }
+
     /**
      * Returns the list of URIs to show.
      * <p>
@@ -349,24 +355,27 @@
         }
 
         // This action deletes all elements in the group from the call log.
-        actions.add(new ViewEntry(android.R.drawable.ic_menu_close_clear_cancel,
-                getString(R.string.recentCalls_removeFromRecentList),
-                new View.OnClickListener() {
-                    @Override
-                    public void onClick(View v) {
-                        StringBuilder callIds = new StringBuilder();
-                        for (Uri callUri : callUris) {
-                            if (callIds.length() != 0) {
-                                callIds.append(",");
+        // We don't have this action for voicemails, because you can just use the trash button.
+        if (!hasVoicemail()) {
+            actions.add(new ViewEntry(android.R.drawable.ic_menu_close_clear_cancel,
+                    getString(R.string.recentCalls_removeFromRecentList),
+                    new View.OnClickListener() {
+                        @Override
+                        public void onClick(View v) {
+                            StringBuilder callIds = new StringBuilder();
+                            for (Uri callUri : callUris) {
+                                if (callIds.length() != 0) {
+                                    callIds.append(",");
+                                }
+                                callIds.append(ContentUris.parseId(callUri));
                             }
-                            callIds.append(ContentUris.parseId(callUri));
-                        }
 
-                        getContentResolver().delete(Calls.CONTENT_URI_WITH_VOICEMAIL,
-                                Calls._ID + " IN (" + callIds + ")", null);
-                        finish();
-                    }
-                }));
+                            getContentResolver().delete(Calls.CONTENT_URI_WITH_VOICEMAIL,
+                                    Calls._ID + " IN (" + callIds + ")", null);
+                            finish();
+                        }
+                    }));
+        }
 
         if (canPlaceCallsTo && !isSipNumber && !isVoicemailNumber) {
             // "Edit the number before calling" is only available for PSTN numbers.
diff --git a/src/com/android/contacts/activities/ContactEditorActivity.java b/src/com/android/contacts/activities/ContactEditorActivity.java
index 28bc3a3..10be943 100644
--- a/src/com/android/contacts/activities/ContactEditorActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorActivity.java
@@ -31,6 +31,7 @@
 import android.app.Activity;
 import android.app.Dialog;
 import android.content.ContentValues;
+import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
@@ -38,6 +39,7 @@
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.RawContacts;
 import android.util.Log;
+import android.view.LayoutInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -76,11 +78,26 @@
 
         setContentView(R.layout.contact_editor_activity);
 
-        // This Activity will always fall back to the "top" Contacts screen when touched on the
-        // app up icon, regardless of launch context.
         ActionBar actionBar = getActionBar();
         if (actionBar != null) {
-            actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP, ActionBar.DISPLAY_HOME_AS_UP);
+            // Inflate a custom action bar that contains the "done" button for saving changes
+            // to the contact
+            LayoutInflater inflater = (LayoutInflater) getSystemService
+                    (Context.LAYOUT_INFLATER_SERVICE);
+            View customActionBarView = inflater.inflate(R.layout.contact_editor_custom_action_bar,
+                    null);
+            View saveMenuItem = customActionBarView.findViewById(R.id.save_menu_item);
+            saveMenuItem.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    mFragment.doSaveAction();
+                }
+            });
+            // Show the custom action bar but hide the home icon and title
+            actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
+                    ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME |
+                    ActionBar.DISPLAY_SHOW_TITLE);
+            actionBar.setCustomView(customActionBarView);
         }
 
         mFragment = (ContactEditorFragment) getFragmentManager().findFragmentById(
@@ -129,17 +146,6 @@
         mFragment.save(SaveMode.CLOSE);
     }
 
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        switch (item.getItemId()) {
-            case android.R.id.home: {
-                mFragment.save(SaveMode.HOME);
-                return true;
-            }
-        }
-        return false;
-    }
-
     private final ContactEditorFragment.Listener mFragmentListener =
             new ContactEditorFragment.Listener() {
         @Override
@@ -176,11 +182,6 @@
         }
 
         @Override
-        public void onDeleteRequested(Uri contactUri) {
-            ContactDeletionInteraction.start(ContactEditorActivity.this, contactUri, true);
-        }
-
-        @Override
         public void onEditOtherContactRequested(
                 Uri contactLookupUri, ArrayList<ContentValues> values) {
             Intent intent = new Intent(Intent.ACTION_EDIT, contactLookupUri);
diff --git a/src/com/android/contacts/calllog/CallLogFragment.java b/src/com/android/contacts/calllog/CallLogFragment.java
index 3383ab2..f61f1de 100644
--- a/src/com/android/contacts/calllog/CallLogFragment.java
+++ b/src/com/android/contacts/calllog/CallLogFragment.java
@@ -974,7 +974,7 @@
 
     private void startCallsQuery() {
         mAdapter.setLoading(true);
-        mCallLogQueryHandler.fetchCalls();
+        mCallLogQueryHandler.fetchAllCalls();
     }
 
     private void startVoicemailStatusQuery() {
@@ -990,6 +990,7 @@
     @Override
     public void onPrepareOptionsMenu(Menu menu) {
         menu.findItem(R.id.delete_all).setVisible(mShowOptionsMenu);
+        menu.findItem(R.id.show_voicemails_only).setVisible(mShowOptionsMenu);
         final MenuItem callSettingsMenuItem = menu.findItem(R.id.menu_call_settings_call_log);
         if (mShowOptionsMenu) {
             callSettingsMenuItem.setVisible(true);
@@ -1006,8 +1007,15 @@
                 ClearCallLogDialog.show(getFragmentManager());
                 return true;
             }
+
+            case R.id.show_voicemails_only: {
+                mCallLogQueryHandler.fetchVoicemailOnly();
+                return true;
+            }
+
+            default:
+                throw new IllegalArgumentException("unknown menu item: " + item.getItemId());
         }
-        return super.onOptionsItemSelected(item);
     }
 
     /*
diff --git a/src/com/android/contacts/calllog/CallLogQueryHandler.java b/src/com/android/contacts/calllog/CallLogQueryHandler.java
index 8569190..fdf55b9 100644
--- a/src/com/android/contacts/calllog/CallLogQueryHandler.java
+++ b/src/com/android/contacts/calllog/CallLogQueryHandler.java
@@ -121,42 +121,57 @@
      * <p>
      * It will asynchronously update the content of the list view when the fetch completes.
      */
-    public void fetchCalls() {
+    public void fetchAllCalls() {
         cancelFetch();
         invalidate();
-        fetchNewCalls();
-        fetchOldCalls();
+        fetchCalls(QUERY_NEW_CALLS_TOKEN, true /*isNew*/, false /*voicemailOnly*/);
+        fetchCalls(QUERY_OLD_CALLS_TOKEN, false /*isNew*/, false /*voicemailOnly*/);
     }
 
+    /**
+     * Fetches the list of calls from the call log but include only the voicemail.
+     * <p>
+     * It will asynchronously update the content of the list view when the fetch completes.
+     */
+    public void fetchVoicemailOnly() {
+        cancelFetch();
+        invalidate();
+        fetchCalls(QUERY_NEW_CALLS_TOKEN, true /*isNew*/, true /*voicemailOnly*/);
+        fetchCalls(QUERY_OLD_CALLS_TOKEN, false /*isNew*/, true /*voicemailOnly*/);
+    }
+
+
     public void fetchVoicemailStatus() {
         startQuery(QUERY_VOICEMAIL_STATUS_TOKEN, null, Status.CONTENT_URI,
                 VoicemailStatusHelperImpl.PROJECTION, null, null, null);
     }
 
-    /** Fetches the list of new calls in the call log. */
-    private void fetchNewCalls() {
-        fetchCalls(QUERY_NEW_CALLS_TOKEN, true);
-    }
-
-    /** Fetch the list of old calls in the call log. */
-    private void fetchOldCalls() {
-        fetchCalls(QUERY_OLD_CALLS_TOKEN, false);
-    }
-
     /** Fetches the list of calls in the call log, either the new one or the old ones. */
-    private void fetchCalls(int token, boolean isNew) {
+    private void fetchCalls(int token, boolean isNew, boolean voicemailOnly) {
         // We need to check for NULL explicitly otherwise entries with where NEW is NULL will not
         // match either the query or its negation.
         String selection =
                 String.format("%s IS NOT NULL AND %s = 1 AND (%s = ? OR %s = ?)",
                         Calls.NEW, Calls.NEW, Calls.TYPE, Calls.TYPE);
-        String[] selectionArgs = new String[]{
-                Integer.toString(Calls.MISSED_TYPE),
-                Integer.toString(Calls.VOICEMAIL_TYPE),
-        };
+        final String[] selectionArgs;
         if (!isNew) {
+            // Negate the query.
             selection = String.format("NOT (%s)", selection);
         }
+        if (voicemailOnly) {
+            // 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),
+            };
+        }
         startQuery(token, null, Calls.CONTENT_URI_WITH_VOICEMAIL,
                 CallLogQuery._PROJECTION, selection, selectionArgs, Calls.DEFAULT_SORT_ORDER);
     }
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index 1921063..9709480 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -106,7 +106,9 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 public class ContactDetailFragment extends Fragment implements FragmentKeyListener, FragmentOverlay,
         OnItemClickListener, OnItemLongClickListener, SelectAccountDialogFragment.Listener {
@@ -131,6 +133,7 @@
     private ListView mListView;
     private ViewAdapter mAdapter;
     private Uri mPrimaryPhoneUri = null;
+    private ViewEntryDimensions mViewEntryDimensions;
 
     private Button mQuickFixButton;
     private QuickFix mQuickFix;
@@ -193,7 +196,8 @@
     private ArrayList<DetailViewEntry> mWebsiteEntries = new ArrayList<DetailViewEntry>();
     private ArrayList<DetailViewEntry> mSipEntries = new ArrayList<DetailViewEntry>();
     private ArrayList<DetailViewEntry> mEventEntries = new ArrayList<DetailViewEntry>();
-    private ArrayList<DetailViewEntry> mOtherEntries = new ArrayList<DetailViewEntry>();
+    private final Map<AccountType, List<DetailViewEntry>> mOtherEntriesMap =
+            new HashMap<AccountType, List<DetailViewEntry>>();
     private ArrayList<ViewEntry> mAllEntries = new ArrayList<ViewEntry>();
     private LayoutInflater mInflater;
 
@@ -235,6 +239,7 @@
         super.onAttach(activity);
         mContext = activity;
         mDefaultCountryIso = ContactsUtils.getCurrentCountryIso(mContext);
+        mViewEntryDimensions = new ViewEntryDimensions(mContext.getResources());
     }
 
     @Override
@@ -643,7 +648,17 @@
                     }
 
                     if (hasSocial || hasData) {
-                        mOtherEntries.add(entry);
+                        // If the account type exists in the hash map, add it as another entry for
+                        // that account type
+                        if (mOtherEntriesMap.containsKey(type)) {
+                            List<DetailViewEntry> listEntries = mOtherEntriesMap.get(type);
+                            listEntries.add(entry);
+                        } else {
+                            // Otherwise create a new list with the entry and add it to the hash map
+                            List<DetailViewEntry> listEntries = new ArrayList<DetailViewEntry>();
+                            listEntries.add(entry);
+                            mOtherEntriesMap.put(type, listEntries);
+                        }
                     }
                 }
             }
@@ -724,8 +739,8 @@
     private void addNetworks() {
         String attribution = ContactDetailDisplayUtils.getAttribution(mContext, mContactData);
         boolean hasAttribution = !TextUtils.isEmpty(attribution);
-        int otherEntriesSize = mOtherEntries.size();
-        if (!hasAttribution && otherEntriesSize == 0) {
+        int networksCount = mOtherEntriesMap.keySet().size();
+        if (!hasAttribution && networksCount == 0) {
             return;
         }
 
@@ -739,19 +754,32 @@
             entry.kind = networkKindTitle;
             entry.data = attribution;
             mAllEntries.add(entry);
+
+            // Add a divider below the attribution if there are network details that will follow
+            if (networksCount > 0) {
+                mAllEntries.add(new SeparatorViewEntry());
+            }
         }
 
         // Add the other entries from third parties
-        for (int i = 0; i < otherEntriesSize; i++) {
-            // Add a divider above the entry. Don't add an entry above the first one if it's the
-            // first one in the DataKind.
-            if (i != 0 || (i == 0 && hasAttribution)) {
-                mAllEntries.add(new SeparatorViewEntry());
+        for (AccountType accountType : mOtherEntriesMap.keySet()) {
+
+            // Add a title for each third party app
+            mAllEntries.add(new NetworkTitleViewEntry(accountType));
+
+            for (DetailViewEntry detailEntry : mOtherEntriesMap.get(accountType)) {
+                // Add indented separator
+                SeparatorViewEntry separatorEntry = new SeparatorViewEntry();
+                separatorEntry.setIsInSubSection(true);
+                mAllEntries.add(separatorEntry);
+
+                // Add indented detail
+                detailEntry.setIsInSubSection(true);
+                mAllEntries.add(detailEntry);
             }
-            mAllEntries.add(mOtherEntries.get(i));
         }
 
-        mOtherEntries.clear();
+        mOtherEntriesMap.clear();
     }
 
     /**
@@ -930,10 +958,23 @@
      */
     private static class SeparatorViewEntry extends ViewEntry {
 
+        /**
+         * Whether or not the entry is in a subsection (if true then the contents will be indented
+         * to the right)
+         */
+        private boolean mIsInSubSection = false;
+
         SeparatorViewEntry() {
             super(ViewAdapter.VIEW_TYPE_SEPARATOR_ENTRY);
         }
 
+        public void setIsInSubSection(boolean isInSubSection) {
+            mIsInSubSection = isInSubSection;
+        }
+
+        public boolean isInSubSection() {
+            return mIsInSubSection;
+        }
     }
 
     /**
@@ -942,13 +983,33 @@
      */
     private static class KindTitleViewEntry extends ViewEntry {
 
-        public final String title;
+        private final String mTitle;
 
         KindTitleViewEntry(String titleText) {
             super(ViewAdapter.VIEW_TYPE_KIND_TITLE_ENTRY);
-            title = titleText;
+            mTitle = titleText;
         }
 
+        public String getTitle() {
+            return mTitle;
+        }
+    }
+
+    /**
+     * A title for a section of contact details from a single 3rd party network.
+     */
+    private static class NetworkTitleViewEntry extends ViewEntry {
+
+        private final AccountType mAccountType;
+
+        NetworkTitleViewEntry(AccountType type) {
+            super(ViewAdapter.VIEW_TYPE_NETWORK_TITLE_ENTRY);
+            mAccountType = type;
+        }
+
+        public AccountType getAccountType() {
+            return mAccountType;
+        }
     }
 
     /**
@@ -956,6 +1017,7 @@
      * list of data.
      */
     static class DetailViewEntry extends ViewEntry implements Collapsible<DetailViewEntry> {
+        // TODO: Make getters/setters for these fields
         public int type = -1;
         public String kind;
         public String typeString;
@@ -979,6 +1041,8 @@
 
         public CharSequence footerLine = null;
 
+        private boolean mIsInSubSection = false;
+
         DetailViewEntry() {
             super(ViewAdapter.VIEW_TYPE_DETAIL_ENTRY);
             isEnabled = true;
@@ -1050,6 +1114,14 @@
             return this;
         }
 
+        public void setIsInSubSection(boolean isInSubSection) {
+            mIsInSubSection = isInSubSection;
+        }
+
+        public boolean isInSubSection() {
+            return mIsInSubSection;
+        }
+
         @Override
         public boolean collapseWith(DetailViewEntry entry) {
             // assert equal collapse keys
@@ -1107,8 +1179,24 @@
         }
     }
 
-    /** Cache of the children views of a row */
-    private static class ViewCache {
+    /**
+     * Cache of the children views for a view that displays a {@link NetworkTitleViewEntry}
+     */
+    private static class NetworkTitleViewCache {
+        public final TextView name;
+        public final ImageView icon;
+
+        public NetworkTitleViewCache(View view) {
+            name = (TextView) view.findViewById(R.id.network_title);
+            icon = (ImageView) view.findViewById(R.id.network_icon);
+        }
+    }
+
+    /**
+     * Cache of the children views of a contact detail entry represented by a
+     * {@link DetailViewEntry}
+     */
+    private static class DetailViewCache {
         public TextView kind;
         public TextView type;
         public TextView data;
@@ -1117,6 +1205,21 @@
         public ImageView secondaryActionButton;
         public View secondaryActionButtonContainer;
         public View secondaryActionDivider;
+
+        public DetailViewCache(View view, OnClickListener secondaryActionClickListener) {
+            kind = (TextView) view.findViewById(R.id.kind);
+            type = (TextView) view.findViewById(R.id.type);
+            data = (TextView) view.findViewById(R.id.data);
+            footer = (TextView) view.findViewById(R.id.footer);
+            presenceIcon = (ImageView) view.findViewById(R.id.presence_icon);
+            secondaryActionButton = (ImageView) view.findViewById(
+                    R.id.secondary_action_button);
+            secondaryActionButtonContainer = view.findViewById(
+                    R.id.secondary_action_button_container);
+            secondaryActionButtonContainer.setOnClickListener(
+                    secondaryActionClickListener);
+            secondaryActionDivider = view.findViewById(R.id.vertical_divider);
+        }
     }
 
     private final class ViewAdapter extends BaseAdapter {
@@ -1124,8 +1227,9 @@
         public static final int VIEW_TYPE_DETAIL_ENTRY = 0;
         public static final int VIEW_TYPE_HEADER_ENTRY = 1;
         public static final int VIEW_TYPE_KIND_TITLE_ENTRY = 2;
-        public static final int VIEW_TYPE_SEPARATOR_ENTRY = 3;
-        private static final int VIEW_TYPE_COUNT = 4;
+        public static final int VIEW_TYPE_NETWORK_TITLE_ENTRY = 3;
+        public static final int VIEW_TYPE_SEPARATOR_ENTRY = 4;
+        private static final int VIEW_TYPE_COUNT = 5;
 
         @Override
         public View getView(int position, View convertView, ViewGroup parent) {
@@ -1133,11 +1237,13 @@
                 case VIEW_TYPE_HEADER_ENTRY:
                     return getHeaderEntryView(convertView, parent);
                 case VIEW_TYPE_SEPARATOR_ENTRY:
-                    return getSeparatorEntryView(convertView, parent);
+                    return getSeparatorEntryView(position, convertView, parent);
                 case VIEW_TYPE_KIND_TITLE_ENTRY:
                     return getKindTitleEntryView(position, convertView, parent);
                 case VIEW_TYPE_DETAIL_ENTRY:
                     return getDetailEntryView(position, convertView, parent);
+                case VIEW_TYPE_NETWORK_TITLE_ENTRY:
+                    return getNetworkTitleEntryView(position, convertView, parent);
                 default:
                     throw new IllegalStateException("Invalid view type ID " +
                             getItemViewType(position));
@@ -1199,11 +1305,16 @@
             return mHeaderView;
         }
 
-        private View getSeparatorEntryView(View convertView, ViewGroup parent) {
-            if (convertView != null) {
-                return convertView;
-            }
-            return mInflater.inflate(R.layout.contact_detail_separator_entry_view, parent, false);
+        private View getSeparatorEntryView(int position, View convertView, ViewGroup parent) {
+            final SeparatorViewEntry entry = (SeparatorViewEntry) getItem(position);
+            final View result = (convertView != null) ? convertView :
+                    mInflater.inflate(R.layout.contact_detail_separator_entry_view, parent, false);
+
+            result.setPadding(entry.isInSubSection() ? mViewEntryDimensions.getWidePaddingLeft() :
+                    mViewEntryDimensions.getPaddingLeft(), 0,
+                    mViewEntryDimensions.getPaddingRight(), 0);
+
+            return result;
         }
 
         private View getKindTitleEntryView(int position, View convertView, ViewGroup parent) {
@@ -1212,7 +1323,28 @@
             final View result = (convertView != null) ? convertView :
                     mInflater.inflate(R.layout.contact_detail_kind_title_entry_view, parent, false);
             final TextView titleTextView = (TextView) result.findViewById(R.id.kind);
-            titleTextView.setText(entry.title);
+            titleTextView.setText(entry.getTitle());
+
+            return result;
+        }
+
+        private View getNetworkTitleEntryView(int position, View convertView, ViewGroup parent) {
+            final NetworkTitleViewEntry entry = (NetworkTitleViewEntry) getItem(position);
+            final View result;
+            final NetworkTitleViewCache viewCache;
+
+            if (convertView != null) {
+                result = convertView;
+                viewCache = (NetworkTitleViewCache) result.getTag();
+            } else {
+                result = mInflater.inflate(R.layout.contact_detail_network_title_entry_view,
+                        parent, false);
+                viewCache = new NetworkTitleViewCache(result);
+                result.setTag(viewCache);
+            }
+
+            viewCache.name.setText(entry.getAccountType().getDisplayLabel(mContext));
+            viewCache.icon.setImageDrawable(entry.getAccountType().getDisplayIcon(mContext));
 
             return result;
         }
@@ -1220,40 +1352,28 @@
         private View getDetailEntryView(int position, View convertView, ViewGroup parent) {
             final DetailViewEntry entry = (DetailViewEntry) getItem(position);
             final View v;
-            final ViewCache viewCache;
+            final DetailViewCache viewCache;
 
             // Check to see if we can reuse convertView
             if (convertView != null) {
                 v = convertView;
-                viewCache = (ViewCache) v.getTag();
+                viewCache = (DetailViewCache) v.getTag();
             } else {
                 // Create a new view if needed
                 v = mInflater.inflate(R.layout.contact_detail_list_item, parent, false);
 
                 // Cache the children
-                viewCache = new ViewCache();
-                viewCache.kind = (TextView) v.findViewById(R.id.kind);
-                viewCache.type = (TextView) v.findViewById(R.id.type);
-                viewCache.data = (TextView) v.findViewById(R.id.data);
-                viewCache.footer = (TextView) v.findViewById(R.id.footer);
-                viewCache.presenceIcon = (ImageView) v.findViewById(R.id.presence_icon);
-                viewCache.secondaryActionButton = (ImageView) v.findViewById(
-                        R.id.secondary_action_button);
-                viewCache.secondaryActionButtonContainer = v.findViewById(
-                        R.id.secondary_action_button_container);
-                viewCache.secondaryActionButtonContainer.setOnClickListener(
-                        mSecondaryActionClickListener);
-                viewCache.secondaryActionDivider = v.findViewById(R.id.vertical_divider);
+                viewCache = new DetailViewCache(v, mSecondaryActionClickListener);
                 v.setTag(viewCache);
             }
 
-            bindView(v, entry);
+            bindDetailView(v, entry);
             return v;
         }
 
-        private void bindView(View view, DetailViewEntry entry) {
+        private void bindDetailView(View view, DetailViewEntry entry) {
             final Resources resources = mContext.getResources();
-            ViewCache views = (ViewCache) view.getTag();
+            DetailViewCache views = (DetailViewCache) view.getTag();
 
             if (!TextUtils.isEmpty(entry.typeString)) {
                 views.type.setText(entry.typeString.toUpperCase());
@@ -1306,6 +1426,12 @@
                 views.secondaryActionButtonContainer.setVisibility(View.GONE);
                 views.secondaryActionDivider.setVisibility(View.GONE);
             }
+
+            view.setPadding(entry.isInSubSection() ? mViewEntryDimensions.getWidePaddingLeft() :
+                    mViewEntryDimensions.getPaddingLeft(),
+                    mViewEntryDimensions.getPaddingTop(),
+                    mViewEntryDimensions.getPaddingRight(),
+                    mViewEntryDimensions.getPaddingBottom());
         }
 
         private void setMaxLines(TextView textView, int maxLines) {
@@ -1402,7 +1528,7 @@
     @Override
     public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
         if (mListener == null) return false;
-        final ViewCache cache = (ViewCache) view.getTag();
+        final DetailViewCache cache = (DetailViewCache) view.getTag();
         if (cache == null) return false;
         CharSequence text = cache.data.getText();
         if (TextUtils.isEmpty(text)) return false;
@@ -1599,6 +1725,51 @@
         }
     }
 
+    /**
+     * This class loads the correct padding values for a contact detail item so they can be applied
+     * dynamically. For example, this supports the case where some detail items can be indented and
+     * need extra padding.
+     */
+    private static class ViewEntryDimensions {
+
+        private final int mWidePaddingLeft;
+        private final int mPaddingLeft;
+        private final int mPaddingRight;
+        private final int mPaddingTop;
+        private final int mPaddingBottom;
+
+        public ViewEntryDimensions(Resources resources) {
+            mPaddingLeft = resources.getDimensionPixelSize(
+                    R.dimen.detail_item_side_margin);
+            mPaddingTop = resources.getDimensionPixelSize(
+                    R.dimen.detail_item_vertical_margin);
+            mWidePaddingLeft = 2 * mPaddingLeft +
+                    resources.getDimensionPixelSize(R.dimen.detail_network_icon_size);
+            mPaddingRight = mPaddingLeft;
+            mPaddingBottom = mPaddingTop;
+        }
+
+        public int getWidePaddingLeft() {
+            return mWidePaddingLeft;
+        }
+
+        public int getPaddingLeft() {
+            return mPaddingLeft;
+        }
+
+        public int getPaddingRight() {
+            return mPaddingRight;
+        }
+
+        public int getPaddingTop() {
+            return mPaddingTop;
+        }
+
+        public int getPaddingBottom() {
+            return mPaddingBottom;
+        }
+    }
+
     public static interface Listener {
         /**
          * User clicked a single item (e.g. mail)
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index 6afe8b9..1ec590c 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -542,10 +542,8 @@
         // ensureKind will not add it, so it is safe to add e.g. Event)
         EntityModifier.ensureKindExists(insert, newAccountType, Phone.CONTENT_ITEM_TYPE);
         EntityModifier.ensureKindExists(insert, newAccountType, Email.CONTENT_ITEM_TYPE);
-        EntityModifier.ensureKindExists(insert, newAccountType, Note.CONTENT_ITEM_TYPE);
         EntityModifier.ensureKindExists(insert, newAccountType, Organization.CONTENT_ITEM_TYPE);
         EntityModifier.ensureKindExists(insert, newAccountType, Event.CONTENT_ITEM_TYPE);
-        EntityModifier.ensureKindExists(insert, newAccountType, Website.CONTENT_ITEM_TYPE);
         EntityModifier.ensureKindExists(insert, newAccountType, StructuredPostal.CONTENT_ITEM_TYPE);
 
         if (mState == null) {
@@ -571,8 +569,8 @@
         final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
         final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
-        int size = mState.size();
-        for (int i = 0; i < size; i++) {
+        int numRawContacts = mState.size();
+        for (int i = 0; i < numRawContacts; i++) {
             // TODO ensure proper ordering of entities in the list
             final EntityDelta entity = mState.get(i);
             final ValuesDelta values = entity.getValues();
@@ -588,10 +586,16 @@
                         R.layout.external_raw_contact_editor_view, mContent, false);
                 ((ExternalRawContactEditorView) editor).setListener(this);
             } else {
-                editor = (BaseRawContactEditorView)
+                final RawContactEditorView rawContactEditor = (RawContactEditorView)
                         inflater.inflate(R.layout.raw_contact_editor_view, mContent, false);
+                // For existing contacts, only show the account header if there is more than 1 raw
+                // contact in the aggregate contact.
+                if (Intent.ACTION_EDIT.equals(mAction)) {
+                    rawContactEditor.setAccountHeaderVisible(numRawContacts > 1);
+                }
+                editor = rawContactEditor;
             }
-            if (Intent.ACTION_INSERT.equals(mAction) && size == 1) {
+            if (Intent.ACTION_INSERT.equals(mAction) && numRawContacts == 1) {
                 final ArrayList<Account> accounts =
                         AccountTypeManager.getInstance(mContext).getAccounts(true);
                 if (accounts.size() > 1) {
@@ -600,6 +604,7 @@
                     disableAccountSwitcher(editor);
                 }
             }
+
             editor.setEnabled(mEnabled);
 
             mContent.addView(editor);
@@ -708,6 +713,7 @@
         // on an existing contact
         final View accountView = editor.findViewById(R.id.account);
         accountView.setBackgroundDrawable(null);
+        accountView.setEnabled(false);
     }
 
     @Override
@@ -717,6 +723,11 @@
 
     @Override
     public void onPrepareOptionsMenu(Menu menu) {
+        // This supports the keyboard shortcut to save changes to a contact but shouldn't be visible
+        // because the custom action bar contains the "save" button now (not the overflow menu).
+        // 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);
         int size = menu.size();
         for (int i = 0; i < size; i++) {
@@ -731,8 +742,6 @@
                 return save(SaveMode.CLOSE);
             case R.id.menu_discard:
                 return revert();
-            case R.id.menu_delete:
-                return doDeleteAction();
             case R.id.menu_split:
                 return doSplitContactAction();
             case R.id.menu_join:
@@ -741,23 +750,6 @@
         return false;
     }
 
-    /**
-     * Delete the entire contact currently being edited, which usually asks for
-     * user confirmation before continuing.
-     */
-    private boolean doDeleteAction() {
-        if (!hasValidState())
-            return false;
-
-        // TODO: Make sure Insert turns into Edit if/once it is autosaved
-        if (Intent.ACTION_INSERT.equals(mAction)) {
-            if (mListener != null) mListener.onReverted();
-        } else {
-            if (mListener != null) mListener.onDeleteRequested(mLookupUri);
-        }
-        return true;
-    }
-
     private boolean doSplitContactAction() {
         if (!hasValidState()) return false;
 
@@ -950,6 +942,10 @@
         if (mListener != null) mListener.onReverted();
     }
 
+    public void doSaveAction() {
+        save(SaveMode.CLOSE);
+    }
+
     public void onJoinCompleted(Uri uri) {
         onSaveCompleted(false, SaveMode.RELOAD, uri);
     }
@@ -1101,11 +1097,6 @@
         void onSaveFinished(Intent resultIntent);
 
         /**
-         * User decided to delete the contact.
-         */
-        void onDeleteRequested(Uri lookupUri);
-
-        /**
          * User switched to editing a different contact (a suggestion from the
          * aggregation engine).
          */
diff --git a/src/com/android/contacts/editor/KindSectionView.java b/src/com/android/contacts/editor/KindSectionView.java
index 8ca7a05..02aa73f 100644
--- a/src/com/android/contacts/editor/KindSectionView.java
+++ b/src/com/android/contacts/editor/KindSectionView.java
@@ -43,6 +43,7 @@
 public class KindSectionView extends LinearLayout implements EditorListener {
     private static final String TAG = "KindSectionView";
 
+    private TextView mTitle;
     private ViewGroup mEditors;
     private View mAddFieldFooter;
     private TextView mAddFieldText;
@@ -93,7 +94,8 @@
 
         mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 
-        mEditors = (ViewGroup)findViewById(R.id.kind_editors);
+        mTitle = (TextView) findViewById(R.id.kind_title);
+        mEditors = (ViewGroup) findViewById(R.id.kind_editors);
         mAddFieldText = (TextView) findViewById(R.id.add_text);
         mAddFieldFooter = findViewById(R.id.add_field_footer);
         mAddFieldFooter.setOnClickListener(new OnClickListener() {
@@ -135,6 +137,7 @@
         mTitleString = (kind.titleRes == -1 || kind.titleRes == 0)
                 ? ""
                 : getResources().getString(kind.titleRes);
+        mTitle.setText(mTitleString.toUpperCase());
 
         // Set "add field" footer message according to MIME type. Some MIME types
         // can only have max 1 field, so the resource ID will be -1 if these sections
@@ -152,6 +155,10 @@
         return mTitleString;
     }
 
+    public void setTitleVisible(boolean visible) {
+        findViewById(R.id.kind_title_layout).setVisibility(visible ? View.VISIBLE : View.GONE);
+    }
+
     /**
      * Build editors for all current {@link #mState} rows.
      */
@@ -275,6 +282,19 @@
         return getEmptyEditors().size() > 0;
     }
 
+    /**
+     * Returns true if all editors are empty.
+     */
+    public boolean isEmpty() {
+        for (int i = 0; i < mEditors.getChildCount(); i++) {
+            View view = mEditors.getChildAt(i);
+            if (!((Editor) view).isEmpty()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     public void addItem() {
         ValuesDelta values = null;
         // If this is a list, we can freely add. If not, only allow adding the first.
diff --git a/src/com/android/contacts/editor/LabeledEditorView.java b/src/com/android/contacts/editor/LabeledEditorView.java
index ddecf5a..91819a2 100644
--- a/src/com/android/contacts/editor/LabeledEditorView.java
+++ b/src/com/android/contacts/editor/LabeledEditorView.java
@@ -31,10 +31,12 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Entity;
+import android.graphics.Color;
 import android.os.Bundle;
 import android.os.Handler;
 import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -62,7 +64,6 @@
     private static final int INPUT_TYPE_CUSTOM = EditorInfo.TYPE_CLASS_TEXT
             | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS;
 
-    private TextView mTitle;
     private Spinner mLabel;
     private EditTypeAdapter mEditTypeAdapter;
     private View mDeleteContainer;
@@ -124,8 +125,6 @@
     @Override
     protected void onFinishInflate() {
 
-        mTitle = (TextView) findViewById(R.id.title);
-
         mLabel = (Spinner) findViewById(R.id.spinner);
         mLabel.setOnItemSelectedListener(mSpinnerListener);
 
@@ -165,26 +164,19 @@
     }
 
     /**
-     * Creates or removes the type/label button. Doesn't do anything if already correctly configured
+     * Configures the visibility of the type label button and enables or disables it properly.
      */
     private void setupLabelButton(boolean shouldExist) {
-        if (mTitle == null) {
-            return;
-        }
         if (shouldExist) {
             mLabel.setEnabled(!mReadOnly && isEnabled());
             mLabel.setVisibility(View.VISIBLE);
-
-            // Since there's a spinner for this editor, use this as the title
-            // instead of the title TextView.
-            mTitle.setVisibility(View.GONE);
         } else {
             mLabel.setVisibility(View.GONE);
         }
     }
 
     /**
-     * Creates or removes the remove button. Doesn't do anything if already correctly configured
+     * Configures the visibility of the "delete" button and enables or disables it properly.
      */
     private void setupDeleteButton() {
         if (mIsDeletable) {
@@ -197,7 +189,7 @@
 
     public void setDeleteButtonVisible(boolean visible) {
         if (mIsDeletable) {
-            mDeleteContainer.setVisibility(visible ? View.VISIBLE : View.GONE);
+            mDeleteContainer.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
         }
     }
 
@@ -275,7 +267,7 @@
         if (mWasEmpty != isEmpty) {
             if (isEmpty) {
                 mListener.onRequest(EditorListener.FIELD_TURNED_EMPTY);
-                if (mIsDeletable) mDeleteContainer.setVisibility(View.GONE);
+                if (mIsDeletable) mDeleteContainer.setVisibility(View.INVISIBLE);
             } else {
                 mListener.onRequest(EditorListener.FIELD_TURNED_NON_EMPTY);
                 if (mIsDeletable) mDeleteContainer.setVisibility(View.VISIBLE);
@@ -318,18 +310,6 @@
         }
         setVisibility(View.VISIBLE);
 
-        // TODO: handle resources from remote packages
-        String titleString = (kind.titleRes == -1 || kind.titleRes == 0)
-                ? ""
-                : getResources().getString(kind.titleRes);
-
-        // If there is a title field, then setup the title (although it may not be shown if there is
-        // a Spinner setup later). There are cases where a title may not be present (i.e. structured
-        // name).
-        if (mTitle != null) {
-            mTitle.setText(titleString.toUpperCase());
-        }
-
         // Display label selector if multiple types available
         final boolean hasTypes = EntityModifier.hasEditTypes(kind);
         setupLabelButton(hasTypes);
@@ -513,6 +493,8 @@
                 text = getContext().getString(type.labelRes);
             }
             textView.setText(text.toUpperCase());
+            textView.setGravity(Gravity.RIGHT);
+            textView.setTextColor(Color.GRAY);
             return view;
         }
     }
diff --git a/src/com/android/contacts/editor/RawContactEditorView.java b/src/com/android/contacts/editor/RawContactEditorView.java
index b0230fc..499b86f 100644
--- a/src/com/android/contacts/editor/RawContactEditorView.java
+++ b/src/com/android/contacts/editor/RawContactEditorView.java
@@ -20,17 +20,16 @@
 import com.android.contacts.R;
 import com.android.contacts.model.AccountType;
 import com.android.contacts.model.AccountType.EditType;
-import com.android.contacts.model.AccountTypeManager;
 import com.android.contacts.model.DataKind;
 import com.android.contacts.model.EntityDelta;
 import com.android.contacts.model.EntityDelta.ValuesDelta;
 import com.android.contacts.model.EntityModifier;
 
-import android.accounts.Account;
 import android.content.Context;
 import android.content.Entity;
 import android.database.Cursor;
 import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
+import android.provider.ContactsContract.CommonDataKinds.Organization;
 import android.provider.ContactsContract.CommonDataKinds.Photo;
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.provider.ContactsContract.Contacts;
@@ -139,7 +138,7 @@
 
         mFields = (ViewGroup)findViewById(R.id.sect_fields);
 
-        mAccountContainer = findViewById(R.id.account);
+        mAccountContainer = findViewById(R.id.anchor_for_account_switcher);
         mAccountIcon = (ImageView) findViewById(R.id.account_icon);
         mAccountTypeTextView = (TextView) findViewById(R.id.account_type);
         mAccountNameTextView = (TextView) findViewById(R.id.account_name);
@@ -153,6 +152,10 @@
         });
     }
 
+    public void setAccountHeaderVisible(boolean visible) {
+        mAccountContainer.setVisibility(visible ? View.VISIBLE : View.GONE);
+    }
+
     /**
      * Set the internal state for this view, given a current
      * {@link EntityDelta} state and the {@link AccountType} that
@@ -160,6 +163,7 @@
      */
     @Override
     public void setState(EntityDelta state, AccountType type, ViewIdGenerator vig) {
+
         mState = state;
 
         // Remove any existing sections
@@ -170,15 +174,13 @@
 
         setId(vig.getId(state, null, null, ViewIdGenerator.NO_VIEW_INDEX));
 
-        // Make sure we have StructuredName
+        // Make sure we have a StructuredName and Organization
         EntityModifier.ensureKindExists(state, type, StructuredName.CONTENT_ITEM_TYPE);
+        EntityModifier.ensureKindExists(state, type, Organization.CONTENT_ITEM_TYPE);
 
         ValuesDelta values = state.getValues();
         mRawContactId = values.getAsLong(RawContacts._ID);
 
-        final ArrayList<Account> accounts =
-                AccountTypeManager.getInstance(mContext).getAccounts(true);
-
         // Fill in the account info
         String accountName = values.getAsString(RawContacts.ACCOUNT_NAME);
         CharSequence accountType = type.getDisplayLabel(mContext);
@@ -237,6 +239,42 @@
                 if (mGroupMembershipView != null) {
                     mGroupMembershipView.setState(state);
                 }
+            } else if (Organization.CONTENT_ITEM_TYPE.equals(mimeType)) {
+                // Create the organization section
+                final KindSectionView section = (KindSectionView) mInflater.inflate(
+                        R.layout.item_kind_section, mFields, false);
+                section.setTitleVisible(false);
+                section.setEnabled(isEnabled());
+                section.setState(kind, state, false, vig);
+
+                // If there is organization info for the contact already, display it
+                if (!section.isEmpty()) {
+                    mFields.addView(section);
+                } else {
+                    // Otherwise provide the user with an "add organization" button that shows the
+                    // EditText fields only when clicked
+                    final View organizationView = mInflater.inflate(
+                            R.layout.organization_editor_view_switcher, mFields, false);
+                    final View addOrganizationButton = organizationView.findViewById(
+                            R.id.add_organization_button);
+                    final ViewGroup organizationSectionViewContainer =
+                            (ViewGroup) organizationView.findViewById(R.id.container);
+
+                    organizationSectionViewContainer.addView(section);
+
+                    // Setup the click listener for the "add organization" button
+                    addOrganizationButton.setOnClickListener(new OnClickListener() {
+                        @Override
+                        public void onClick(View v) {
+                            // Once the user expands the organization field, the user cannot
+                            // collapse them again.
+                            addOrganizationButton.setVisibility(View.GONE);
+                            organizationSectionViewContainer.setVisibility(View.VISIBLE);
+                        }
+                    });
+
+                    mFields.addView(organizationView);
+                }
             } else {
                 // Otherwise use generic section-based editors
                 if (kind.fieldList == null) continue;
@@ -361,8 +399,13 @@
             View child = mFields.getChildAt(i);
             if (child instanceof KindSectionView) {
                 final KindSectionView sectionView = (KindSectionView) child;
-                // not a list and already exists? ignore
+                // If the section is already visible (has 1 or more editors), then don't offer the
+                // option to add this type of field in the popup menu
+                if (sectionView.getEditorCount() > 0) {
+                    continue;
+                }
                 DataKind kind = sectionView.getKind();
+                // not a list and already exists? ignore
                 if (!kind.isList && sectionView.getEditorCount() != 0) {
                     continue;
                 }
diff --git a/src/com/android/contacts/model/BaseAccountType.java b/src/com/android/contacts/model/BaseAccountType.java
index 5c3e245..c2e8a53 100644
--- a/src/com/android/contacts/model/BaseAccountType.java
+++ b/src/com/android/contacts/model/BaseAccountType.java
@@ -100,7 +100,7 @@
     protected DataKind addDataKindStructuredName(Context context) {
         DataKind kind = addKind(new DataKind(StructuredName.CONTENT_ITEM_TYPE,
                 R.string.nameLabelsGroup, -1, -1, true, R.layout.structured_name_editor_view,
-                android.R.style.TextAppearance_Large, -1));
+                android.R.style.TextAppearance_Medium, -1));
         kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
         kind.actionBody = new SimpleInflater(Nickname.NAME);
 
@@ -130,7 +130,7 @@
     protected DataKind addDataKindDisplayName(Context context) {
         DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME,
                 R.string.nameLabelsGroup, -1, -1, true, R.layout.text_fields_editor_view,
-                android.R.style.TextAppearance_Large, -1));
+                android.R.style.TextAppearance_Medium, -1));
         kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
         kind.actionBody = new SimpleInflater(Nickname.NAME);
 
@@ -208,7 +208,7 @@
     protected DataKind addDataKindPhone(Context context) {
         DataKind kind = addKind(new DataKind(Phone.CONTENT_ITEM_TYPE, R.string.phoneLabelsGroup,
                 android.R.drawable.sym_action_call, 10, true,
-                R.layout.text_fields_editor_view, android.R.style.TextAppearance_Large,
+                R.layout.text_fields_editor_view, android.R.style.TextAppearance_Medium,
                 R.string.add_phone));
         kind.iconAltRes = R.drawable.sym_action_sms;
         kind.actionHeader = new PhoneActionInflater();
@@ -286,7 +286,7 @@
         kind.fieldList = Lists.newArrayList();
         kind.fieldList.add(
                 new EditField(StructuredPostal.FORMATTED_ADDRESS, R.string.postal_address,
-                        FLAGS_POSTAL).setMinLines(3));
+                        FLAGS_POSTAL).setMinLines(1));
 
         return kind;
     }
diff --git a/src/com/android/contacts/model/ExchangeAccountType.java b/src/com/android/contacts/model/ExchangeAccountType.java
index 8db4a7b..5b007aa 100644
--- a/src/com/android/contacts/model/ExchangeAccountType.java
+++ b/src/com/android/contacts/model/ExchangeAccountType.java
@@ -65,7 +65,7 @@
     protected DataKind addDataKindStructuredName(Context context) {
         DataKind kind = addKind(new DataKind(StructuredName.CONTENT_ITEM_TYPE,
                 R.string.nameLabelsGroup, -1, -1, true,
-                R.layout.structured_name_editor_view, android.R.style.TextAppearance_Large, -1));
+                R.layout.structured_name_editor_view, android.R.style.TextAppearance_Medium, -1));
         kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
         kind.actionBody = new SimpleInflater(Nickname.NAME);
 
@@ -95,7 +95,7 @@
     protected DataKind addDataKindDisplayName(Context context) {
         DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME,
                 R.string.nameLabelsGroup, -1, -1, true,
-                R.layout.text_fields_editor_view, android.R.style.TextAppearance_Large, -1));
+                R.layout.text_fields_editor_view, android.R.style.TextAppearance_Medium, -1));
 
         boolean displayOrderPrimary =
                 context.getResources().getBoolean(R.bool.config_editor_field_order_primary);
diff --git a/tests/src/com/android/contacts/CallDetailActivityTest.java b/tests/src/com/android/contacts/CallDetailActivityTest.java
index a36216e..665bc92 100644
--- a/tests/src/com/android/contacts/CallDetailActivityTest.java
+++ b/tests/src/com/android/contacts/CallDetailActivityTest.java
@@ -17,6 +17,7 @@
 package com.android.contacts;
 
 import com.android.contacts.util.IntegrationTestUtils;
+import com.android.contacts.util.LocaleTestUtils;
 import com.google.common.base.Preconditions;
 
 import android.app.Activity;
@@ -28,6 +29,8 @@
 import android.provider.CallLog;
 import android.test.ActivityInstrumentationTestCase2;
 
+import java.util.Locale;
+
 /**
  * Unit tests for the {@link CallDetailActivity}.
  */
@@ -35,6 +38,7 @@
     private static final String FAKE_VOICEMAIL_URI_STRING = "content://fake_uri";
     private Uri mUri;
     private IntegrationTestUtils mTestUtils;
+    private LocaleTestUtils mLocaleTestUtils;
 
     public CallDetailActivityTest() {
         super(CallDetailActivity.class);
@@ -47,10 +51,16 @@
         // screenshots look weak.
         setActivityInitialTouchMode(true);
         mTestUtils = new IntegrationTestUtils(getInstrumentation());
+        // Some of the tests rely on the text that appears on screen - safest to force a
+        // specific locale.
+        mLocaleTestUtils = new LocaleTestUtils(getInstrumentation().getTargetContext());
+        mLocaleTestUtils.setLocale(Locale.US);
     }
 
     @Override
     protected void tearDown() throws Exception {
+        mLocaleTestUtils.restoreLocale();
+        mLocaleTestUtils = null;
         cleanUpUri();
         mTestUtils = null;
         super.tearDown();
@@ -61,7 +71,7 @@
      * <p>
      * The repro steps for this crash were to open a voicemail that does not have an attachment,
      * then click the play button (which just reported an error), then after that try to adjust the
-     * rate.
+     * rate.  See http://b/5047879.
      */
     public void testClickIncreaseRateButtonWithInvalidVoicemailDoesNotCrash() throws Throwable {
         setActivityIntentForTestVoicemailEntry();
@@ -76,6 +86,28 @@
         getActivity();
     }
 
+    /**
+     * Test for bug where voicemails should not have remove-from-call-log entry.
+     * <p>
+     * See http://b/5054103.
+     */
+    public void testVoicemailDoesNotHaveRemoveFromCallLog() throws Throwable {
+        setActivityIntentForTestVoicemailEntry();
+        getActivity();
+        assertEquals(0, countTextViewsContaining("Remove from call log"));
+    }
+
+    /** Test to check that I haven't broken the remove-from-call-log entry from regular calls. */
+    public void testRegularCallDoesHaveRemoveFromCallLog() throws Throwable {
+        setActivityIntentForTestCallEntry();
+        getActivity();
+        assertEquals(1, countTextViewsContaining("Remove from call log"));
+    }
+
+    private int countTextViewsContaining(String text) throws Throwable {
+        return mTestUtils.getTextViewsWithString(getActivity(), text).size();
+    }
+
     private void setActivityIntentForTestCallEntry() {
         createTestCallEntry(false);
         setActivityIntent(new Intent(Intent.ACTION_VIEW, mUri));
diff --git a/tests/src/com/android/contacts/util/IntegrationTestUtils.java b/tests/src/com/android/contacts/util/IntegrationTestUtils.java
index 45dc981..a61ea57 100644
--- a/tests/src/com/android/contacts/util/IntegrationTestUtils.java
+++ b/tests/src/com/android/contacts/util/IntegrationTestUtils.java
@@ -27,9 +27,13 @@
 import android.content.Context;
 import android.os.PowerManager;
 import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
 
 import junit.framework.Assert;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.FutureTask;
@@ -118,4 +122,55 @@
             }
         }
     }
+
+    /**
+     * Gets all {@link TextView} objects whose {@link TextView#getText()} contains the given text as
+     * a substring.
+     */
+    public List<TextView> getTextViewsWithString(final Activity activity, final String text)
+            throws Throwable {
+        return runOnUiThreadAndGetTheResult(new Callable<List<TextView>>() {
+            @Override
+            public List<TextView> call() throws Exception {
+                List<TextView> matchingViews = new ArrayList<TextView>();
+                for (TextView textView : getAllViews(TextView.class, getRootView(activity))) {
+                    if (textView.getText().toString().contains(text)) {
+                        matchingViews.add(textView);
+                    }
+                }
+                return matchingViews;
+            }
+        });
+    }
+
+    /** Find the root view for a given activity. */
+    public static View getRootView(Activity activity) {
+        return activity.findViewById(android.R.id.content).getRootView();
+    }
+
+    /**
+     * Gets a list of all views of a given type, rooted at the given parent.
+     * <p>
+     * This method will recurse down through all {@link ViewGroup} instances looking for
+     * {@link View} instances of the supplied class type. Specifically it will use the
+     * {@link Class#isAssignableFrom(Class)} method as the test for which views to add to the list,
+     * so if you provide {@code View.class} as your type, you will get every view. The parent itself
+     * will be included also, should it be of the right type.
+     * <p>
+     * This call manipulates the ui, and as such should only be called from the application's main
+     * thread.
+     */
+    private static <T extends View> List<T> getAllViews(final Class<T> clazz, final View parent) {
+        List<T> results = new ArrayList<T>();
+        if (parent.getClass().equals(clazz)) {
+            results.add(clazz.cast(parent));
+        }
+        if (parent instanceof ViewGroup) {
+            ViewGroup viewGroup = (ViewGroup) parent;
+            for (int i = 0; i < viewGroup.getChildCount(); ++i) {
+                results.addAll(getAllViews(clazz, viewGroup.getChildAt(i)));
+            }
+        }
+        return results;
+    }
 }