Merge "Make the CallLogAdapter a static nested class."
diff --git a/res/drawable-hdpi/sym_action_audiochat_holo_dark.png b/res/drawable-hdpi/sym_action_audiochat_holo_dark.png
new file mode 100644
index 0000000..d4e3329
--- /dev/null
+++ b/res/drawable-hdpi/sym_action_audiochat_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/sym_action_videochat_holo_dark.png b/res/drawable-hdpi/sym_action_videochat_holo_dark.png
new file mode 100644
index 0000000..821940a
--- /dev/null
+++ b/res/drawable-hdpi/sym_action_videochat_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/sym_action_audiochat_holo_dark.png b/res/drawable-mdpi/sym_action_audiochat_holo_dark.png
new file mode 100644
index 0000000..848404d
--- /dev/null
+++ b/res/drawable-mdpi/sym_action_audiochat_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/sym_action_videochat_holo_dark.png b/res/drawable-mdpi/sym_action_videochat_holo_dark.png
new file mode 100644
index 0000000..9112e87
--- /dev/null
+++ b/res/drawable-mdpi/sym_action_videochat_holo_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/sym_action_audiochat_holo_dark.png b/res/drawable-xhdpi/sym_action_audiochat_holo_dark.png
new file mode 100644
index 0000000..216d34f
--- /dev/null
+++ b/res/drawable-xhdpi/sym_action_audiochat_holo_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/sym_action_videochat_holo_dark.png b/res/drawable-xhdpi/sym_action_videochat_holo_dark.png
new file mode 100644
index 0000000..5011489
--- /dev/null
+++ b/res/drawable-xhdpi/sym_action_videochat_holo_dark.png
Binary files differ
diff --git a/res/layout-sw580dp-w1000dp/contact_detail_container.xml b/res/layout-sw580dp-w1000dp/contact_detail_container.xml
index be91296..1d4ea35 100644
--- a/res/layout-sw580dp-w1000dp/contact_detail_container.xml
+++ b/res/layout-sw580dp-w1000dp/contact_detail_container.xml
@@ -16,7 +16,7 @@
 
 <!--
   Two-column layout for a contact with social updates. If the contact does not
-  have social updates, then the second fragment view will just be hidden.
+  have social updates, then the second fragment container will just be hidden.
 -->
 
 <LinearLayout
@@ -26,14 +26,24 @@
     android:scrollbars="none"
     android:orientation="horizontal">
 
-    <fragment class="com.android.contacts.detail.ContactDetailFragment"
-        android:id="@+id/about_fragment"
+    <!--
+      Container for the "About" fragment on the contact card for a contact
+      with social updates. This view ID must match with a view ID in the layout
+      that is used after an orientation change.
+    -->
+    <FrameLayout
+        android:id="@+id/about_fragment_container"
         android:layout_width="0dip"
         android:layout_height="match_parent"
         android:layout_weight="1" />
 
-    <fragment class="com.android.contacts.detail.ContactDetailUpdatesFragment"
-        android:id="@+id/updates_fragment"
+    <!--
+      Container for the "Updates" fragment on the contact card for a contact
+      with social updates. This view ID must match with a view ID in the layout
+      that is used after an orientation change.
+    -->
+    <FrameLayout
+        android:id="@+id/updates_fragment_container"
         android:layout_width="306dip"
         android:layout_height="match_parent" />
 
diff --git a/res/layout-sw580dp-w1000dp/contact_detail_updates_fragment.xml b/res/layout-sw580dp-w1000dp/contact_detail_updates_fragment.xml
index 9b63ccf..427f369 100644
--- a/res/layout-sw580dp-w1000dp/contact_detail_updates_fragment.xml
+++ b/res/layout-sw580dp-w1000dp/contact_detail_updates_fragment.xml
@@ -14,51 +14,22 @@
      limitations under the License.
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts"
     android:id="@+id/contact_detail_updates_fragment"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:padding="16dip">
 
-    <ScrollView
+    <include
+        android:id="@+id/title"
+        layout="@layout/contact_detail_kind_title_entry_view" />
+
+    <ListView android:id="@android:id/list"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="@color/background_social_updates">
+        android:layout_height="wrap_content"
+        android:background="@color/background_social_updates"
+        android:divider="@null"/>
 
-        <LinearLayout
-            android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingTop="@dimen/detail_update_section_top_padding">
-
-            <include
-                android:id="@+id/title"
-                layout="@layout/contact_detail_kind_title_entry_view" />
-
-            <LinearLayout
-                android:id="@+id/update_list"
-                android:orientation="vertical"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingLeft="@dimen/detail_update_section_side_padding"
-                android:paddingRight="@dimen/detail_update_section_side_padding" />
-        </LinearLayout>
-
-    </ScrollView>
-
-    <View
-        android:id="@+id/alpha_overlay"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="@android:color/black"
-        android:alpha=".50"
-        android:visibility="gone"/>
-
-    <View
-        android:id="@+id/touch_intercept_overlay"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="@android:color/transparent"
-        android:visibility="gone"/>
-
-</FrameLayout>
+</LinearLayout>
diff --git a/res/layout-sw580dp-w1000dp/updates_header_contact.xml b/res/layout-sw580dp-w1000dp/updates_header_contact.xml
new file mode 100644
index 0000000..da63d20
--- /dev/null
+++ b/res/layout-sw580dp-w1000dp/updates_header_contact.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!--
+  This is a header entry in the contact updates list.
+  This is empty because there is no header in this case.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="0dip"/>
diff --git a/res/layout-sw580dp/contact_detail_updates_fragment.xml b/res/layout-sw580dp/contact_detail_updates_fragment.xml
index ce3f661..d73275e 100644
--- a/res/layout-sw580dp/contact_detail_updates_fragment.xml
+++ b/res/layout-sw580dp/contact_detail_updates_fragment.xml
@@ -14,52 +14,18 @@
      limitations under the License.
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts"
     android:id="@+id/contact_detail_updates_fragment"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <ScrollView
+    <ListView android:id="@android:id/list"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:background="@color/background_social_updates">
-
-        <LinearLayout
-            android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingTop="@dimen/detail_update_section_top_padding">
-
-            <!-- Add a first item that gives us enough space to show the carousel -->
-            <view
-                class="com.android.contacts.widget.ProportionalLayout"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                ex:ratio="0.66"
-                ex:direction="widthToHeight">
-
-                <!-- Put a dummy view here because the ProportionalLayout requires one -->
-                <View
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent" />
-
-            </view>
-
-            <include
-                android:id="@+id/title"
-                layout="@layout/contact_detail_kind_title_entry_view" />
-
-            <LinearLayout
-                android:id="@+id/update_list"
-                android:orientation="vertical"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingLeft="@dimen/detail_update_section_side_padding"
-                android:paddingRight="@dimen/detail_update_section_side_padding" />
-        </LinearLayout>
-
-    </ScrollView>
+        android:background="@color/background_social_updates"
+        android:divider="@null"/>
 
     <View
         android:id="@+id/alpha_overlay"
diff --git a/res/layout-sw580dp/people_activity.xml b/res/layout-sw580dp/people_activity.xml
index 13adfa9..1d02042 100644
--- a/res/layout-sw580dp/people_activity.xml
+++ b/res/layout-sw580dp/people_activity.xml
@@ -83,6 +83,7 @@
 
             <!-- This layout includes all possible views needed for a contact detail page -->
             <include
+                android:id="@+id/contact_detail_container"
                 layout="@layout/contact_detail_container"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"/>
diff --git a/res/layout-sw580dp/updates_header_contact.xml b/res/layout-sw580dp/updates_header_contact.xml
new file mode 100644
index 0000000..2f2177f
--- /dev/null
+++ b/res/layout-sw580dp/updates_header_contact.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!--
+  This is a header entry in the contact updates list.
+  Add a first item that gives us enough space to show the carousel
+-->
+<view
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts"
+    class="com.android.contacts.widget.ProportionalLayout"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    ex:ratio="0.66"
+    ex:direction="widthToHeight">
+
+    <!-- Put a dummy view here because the ProportionalLayout requires one -->
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+</view>
diff --git a/res/layout-w470dp/contact_detail_updates_fragment.xml b/res/layout-w470dp/contact_detail_updates_fragment.xml
index 0c8380c..92ddd8c 100644
--- a/res/layout-w470dp/contact_detail_updates_fragment.xml
+++ b/res/layout-w470dp/contact_detail_updates_fragment.xml
@@ -14,51 +14,21 @@
      limitations under the License.
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts"
     android:id="@+id/contact_detail_updates_fragment"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:orientation="vertical">
 
-    <ScrollView
+    <include
+        android:id="@+id/title"
+        layout="@layout/contact_detail_kind_title_entry_view" />
+
+    <ListView android:id="@android:id/list"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="@color/background_social_updates">
+        android:layout_height="wrap_content"
+        android:background="@color/background_social_updates"
+        android:divider="@null"/>
 
-        <LinearLayout
-            android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingTop="@dimen/detail_update_section_top_padding">
-
-            <include
-                android:id="@+id/title"
-                layout="@layout/contact_detail_kind_title_entry_view" />
-
-            <LinearLayout
-                android:id="@+id/update_list"
-                android:orientation="vertical"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingLeft="@dimen/detail_update_section_side_padding"
-                android:paddingRight="@dimen/detail_update_section_side_padding" />
-        </LinearLayout>
-
-    </ScrollView>
-
-    <View
-        android:id="@+id/alpha_overlay"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="@android:color/black"
-        android:alpha=".50"
-        android:visibility="gone"/>
-
-    <View
-        android:id="@+id/touch_intercept_overlay"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="?android:attr/selectableItemBackground"
-        android:visibility="gone"/>
-
-</FrameLayout>
+</LinearLayout>
diff --git a/res/layout-w470dp/updates_header_contact.xml b/res/layout-w470dp/updates_header_contact.xml
new file mode 100644
index 0000000..da63d20
--- /dev/null
+++ b/res/layout-w470dp/updates_header_contact.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!--
+  This is a header entry in the contact updates list.
+  This is empty because there is no header in this case.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="0dip"/>
diff --git a/res/layout/contact_detail_container.xml b/res/layout/contact_detail_container.xml
index 3991e5c..9204b62 100644
--- a/res/layout/contact_detail_container.xml
+++ b/res/layout/contact_detail_container.xml
@@ -43,12 +43,7 @@
         android:layout_alignParentTop="true"
         android:layout_alignParentLeft="true"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"/>
-
-    <fragment
-        android:id="@+id/contact_detail_fragment"
-        class="com.android.contacts.detail.ContactDetailFragment"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"/>
+        android:layout_height="wrap_content"
+        android:visibility="gone"/>
 
 </RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/contact_detail_updates_fragment.xml b/res/layout/contact_detail_updates_fragment.xml
index 95eb0a5..2393ace 100644
--- a/res/layout/contact_detail_updates_fragment.xml
+++ b/res/layout/contact_detail_updates_fragment.xml
@@ -14,64 +14,17 @@
      limitations under the License.
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts"
     android:id="@+id/contact_detail_updates_fragment"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <ScrollView
+    <ListView android:id="@android:id/list"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:background="@color/background_social_updates">
-
-        <LinearLayout
-            android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingTop="@dimen/detail_update_section_top_padding">
-
-            <!-- Add a first item that gives us enough space to show the carousel -->
-            <view
-                class="com.android.contacts.widget.ProportionalLayout"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                ex:ratio="0.5"
-                ex:direction="widthToHeight">
-
-                <!-- Put a dummy view here because the ProportionalLayout requires one -->
-                <View
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent" />
-
-            </view>
-
-            <include
-                android:id="@+id/title"
-                layout="@layout/contact_detail_kind_title_entry_view" />
-
-            <LinearLayout
-                android:id="@+id/update_list"
-                android:orientation="vertical"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content" />
-        </LinearLayout>
-
-    </ScrollView>
-
-    <View
-        android:id="@+id/alpha_overlay"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="@android:color/black"
-        android:alpha=".50"
-        android:visibility="gone"/>
-
-    <View
-        android:id="@+id/touch_intercept_overlay"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="@android:color/transparent"
-        android:visibility="gone"/>
+        android:background="@color/background_social_updates"
+        android:divider="@null"/>
 
 </FrameLayout>
diff --git a/res/layout/contact_list_filter_custom.xml b/res/layout/contact_list_filter_custom.xml
index 98925be..195ff1a 100644
--- a/res/layout/contact_list_filter_custom.xml
+++ b/res/layout/contact_list_filter_custom.xml
@@ -42,14 +42,6 @@
         style="?android:attr/buttonBarStyle">
 
         <Button
-            android:id="@+id/btn_done"
-            style="?android:attr/buttonBarButtonStyle"
-            android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:text="@android:string/ok" />
-
-        <Button
             android:id="@+id/btn_discard"
             style="?android:attr/buttonBarButtonStyle"
             android:layout_width="0dip"
@@ -57,5 +49,13 @@
             android:layout_weight="1"
             android:text="@android:string/cancel" />
 
+        <Button
+            android:id="@+id/btn_done"
+            style="?android:attr/buttonBarButtonStyle"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:text="@android:string/ok" />
+
     </LinearLayout>
 </LinearLayout>
diff --git a/res/layout/updates_header_contact.xml b/res/layout/updates_header_contact.xml
new file mode 100644
index 0000000..d401f05
--- /dev/null
+++ b/res/layout/updates_header_contact.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!--
+  This is a header entry in the contact updates list.
+  Add a first item that gives us enough space to show the carousel
+-->
+<view
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts"
+    class="com.android.contacts.widget.ProportionalLayout"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    ex:ratio="0.5"
+    ex:direction="widthToHeight">
+
+    <!-- Put a dummy view here because the ProportionalLayout requires one -->
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+</view>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8cd1d8e..5bb6c2b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -604,8 +604,11 @@
     <!-- A nicely formatted call duration displayed when viewing call details. For example "42 mins 28 secs" -->
     <string name="callDetailsDurationFormat"><xliff:g id="minutes" example="42">%s</xliff:g> mins <xliff:g id="seconds" example="28">%s</xliff:g> secs</string>
 
-    <!-- A list separator for the Favorites tab indicating that items below it are frequently contacted contacts rather than starred contacts -->
-    <string name="favoritesFrquentSeparator">Frequently contacted</string>
+    <!-- The text displayed on the divider for the Favorites tab in People app indicating that items below it are frequently contacted [CHAR LIMIT = 39] -->
+    <string name="favoritesFrequentContacted">Frequently contacted</string>
+
+    <!-- The text displayed on the divider for the Favorites tab in Phone app indicating that items below it are frequently called as opposed to starred contacts [CHAR LIMIT = 39] -->
+    <string name="favoritesFrequentCalled">Frequently called</string>
 
     <!-- Dialog title when prompting before creating a contact -->
     <string name="add_contact_dlg_title">Add contact</string>
diff --git a/src/com/android/contacts/activities/ContactDetailActivity.java b/src/com/android/contacts/activities/ContactDetailActivity.java
index 3dffd71..53c7f5e 100644
--- a/src/com/android/contacts/activities/ContactDetailActivity.java
+++ b/src/com/android/contacts/activities/ContactDetailActivity.java
@@ -75,8 +75,6 @@
 
     private static final String KEY_CONTACT_HAS_UPDATES = "contactHasUpdates";
     private static final String KEY_CURRENT_PAGE_INDEX = "currentPageIndex";
-    private static final String KEY_DETAIL_FRAGMENT_TAG = "detailFragTag";
-    private static final String KEY_UPDATES_FRAGMENT_TAG = "updatesFragTag";
 
     public static final int FRAGMENT_COUNT = 2;
 
@@ -156,6 +154,7 @@
 
         mDetailFragment.setListener(mFragmentListener);
         mDetailFragment.setVerticalScrollListener(mVerticalScrollListener);
+        mUpdatesFragment.setVerticalScrollListener(mVerticalScrollListener);
         mDetailFragment.setData(mLookupUri, mContactData);
         mUpdatesFragment.setData(mLookupUri, mContactData);
 
@@ -273,11 +272,6 @@
         super.onSaveInstanceState(outState);
         outState.putBoolean(KEY_CONTACT_HAS_UPDATES, mContactHasUpdates);
         outState.putInt(KEY_CURRENT_PAGE_INDEX, getCurrentPage());
-        if (mViewPager != null) {
-            outState.putString(KEY_DETAIL_FRAGMENT_TAG, mDetailFragment.getTag());
-            outState.putString(KEY_UPDATES_FRAGMENT_TAG, mUpdatesFragment.getTag());
-            return;
-        }
     }
 
     private final ContactLoaderFragmentListener mLoaderFragmentListener =
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index 48fd49d..282e0b3 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -122,8 +122,6 @@
 
     private ContactDetailFragment mContactDetailFragment;
     private ContactDetailUpdatesFragment mContactDetailUpdatesFragment;
-    private final ContactDetailFragmentListener mContactDetailFragmentListener =
-            new ContactDetailFragmentListener();
 
     private ContactLoaderFragment mContactDetailLoaderFragment;
     private final ContactDetailLoaderFragmentListener mContactDetailLoaderFragmentListener =
@@ -226,7 +224,6 @@
     public void onAttachFragment(Fragment fragment) {
         if (fragment instanceof ContactDetailFragment) {
             mContactDetailFragment = (ContactDetailFragment) fragment;
-            mContactDetailFragment.setListener(mContactDetailFragmentListener);
         } else if (fragment instanceof ContactDetailUpdatesFragment) {
             mContactDetailUpdatesFragment = (ContactDetailUpdatesFragment) fragment;
         } else if (fragment instanceof ContactsUnavailableFragment) {
@@ -379,21 +376,21 @@
 
             mContactDetailLoaderFragment = getFragment(R.id.contact_detail_loader_fragment);
             mContactDetailLoaderFragment.setListener(mContactDetailLoaderFragmentListener);
+            mContactDetailLoaderFragment.setRetainInstance(true);
 
             mGroupDetailFragment = getFragment(R.id.group_detail_fragment);
             mGroupDetailFragment.setListener(mGroupDetailFragmentListener);
             mGroupDetailFragment.setQuickContact(true);
 
-            transaction.hide(mContactDetailFragment);
+            if (mContactDetailFragment != null) {
+                transaction.hide(mContactDetailFragment);
+            }
             transaction.hide(mGroupDetailFragment);
 
             // Configure contact details
-            ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
-            ContactDetailTabCarousel tabCarousel = (ContactDetailTabCarousel)
-                    findViewById(R.id.tab_carousel);
-            mContactDetailLayoutController = new ContactDetailLayoutController(
-                    getFragmentManager(), viewPager, tabCarousel,
-                    mContactDetailFragmentListener);
+            mContactDetailLayoutController = new ContactDetailLayoutController(this, savedState,
+                    getFragmentManager(), findViewById(R.id.contact_detail_container),
+                    new ContactDetailFragmentListener());
         }
         transaction.commit();
         fragmentManager.executePendingTransactions();
@@ -1066,13 +1063,6 @@
                     if (isFinishing()) {
                         return;
                     }
-                    if (!mContactDetailLayoutController.isInitialized()) {
-                        mContactDetailLayoutController.setContactDetailFragment(
-                                mContactDetailFragment);
-                        mContactDetailLayoutController.setContactDetailUpdatesFragment(
-                                mContactDetailUpdatesFragment);
-                        mContactDetailLayoutController.initialize();
-                    }
                     mContactDetailLayoutController.setContactData(result);
                 }
             });
@@ -1570,14 +1560,6 @@
     }
 
     @Override
-    protected void onRestoreInstanceState(Bundle inState) {
-        super.onRestoreInstanceState(inState);
-        if (mContactDetailLayoutController != null) {
-            mContactDetailLayoutController.onRestoreInstanceState(inState);
-        }
-    }
-
-    @Override
     public DialogManager getDialogManager() {
         return mDialogManager;
     }
diff --git a/src/com/android/contacts/calllog/ClearCallLogDialog.java b/src/com/android/contacts/calllog/ClearCallLogDialog.java
index 0f999bd..426732a 100644
--- a/src/com/android/contacts/calllog/ClearCallLogDialog.java
+++ b/src/com/android/contacts/calllog/ClearCallLogDialog.java
@@ -52,7 +52,7 @@
                 final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
                     @Override
                     protected Void doInBackground(Void... params) {
-                        resolver.delete(Calls.CONTENT_URI_WITH_VOICEMAIL, null, null);
+                        resolver.delete(Calls.CONTENT_URI, null, null);
                         return null;
                     }
                     @Override
diff --git a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
index 7144dfb..e88e5e8 100644
--- a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
+++ b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
@@ -263,8 +263,7 @@
         }
     }
 
-    @VisibleForTesting
-    static void addStreamItemToContainer(LayoutInflater inflater, Context context,
+    public static View addStreamItemToContainer(LayoutInflater inflater, Context context,
             StreamItemEntry streamItem, LinearLayout streamContainer,
             View.OnClickListener listener) {
         View oneColumnView = inflater.inflate(R.layout.stream_item_one_column,
@@ -336,7 +335,11 @@
             }
         }
 
-        streamContainer.addView(oneColumnView);
+        if (streamContainer != null) {
+            streamContainer.addView(oneColumnView);
+        }
+
+        return oneColumnView;
     }
 
     @VisibleForTesting
@@ -426,4 +429,4 @@
         }
     }
 
-}
\ No newline at end of file
+}
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index 02394f2..02e74dd 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -223,6 +223,9 @@
 
     private boolean mTransitionAnimationRequested;
 
+    private boolean mIsUniqueNumber;
+    private boolean mIsUniqueEmail;
+
     public ContactDetailFragment() {
         // Explicit constructor for inflation
     }
@@ -422,6 +425,9 @@
         Collapser.collapseList(mPostalEntries);
         Collapser.collapseList(mImEntries);
 
+        mIsUniqueNumber = mPhoneEntries.size() == 1;
+        mIsUniqueEmail = mEmailEntries.size() == 1;
+
         // Make one aggregated list of all entries for display to the user.
         setupFlattenedList();
 
@@ -1716,36 +1722,23 @@
 
         String selectedMimeType = selectedEntry.mimetype;
 
+        // Defaults to true will only enable the detail to be copied to the clipboard.
+        boolean isUniqueMimeType = true;
+
         // Only allow primary support for Phone and Email content types
-        if (Phone.CONTENT_ITEM_TYPE.equals(selectedMimeType) ||
-                Email.CONTENT_ITEM_TYPE.equals(selectedMimeType)) {
+        if (Phone.CONTENT_ITEM_TYPE.equals(selectedMimeType)) {
+            isUniqueMimeType = mIsUniqueNumber;
+        } else if (Email.CONTENT_ITEM_TYPE.equals(selectedMimeType)) {
+            isUniqueMimeType = mIsUniqueEmail;
+        }
 
-            // Used to determine if entry is the only mime type of its kind
-            boolean isUniqueMimeType = true;
-
-            // Checking for unique mime type
-            for (int positionCounter = 0; positionCounter < mAllEntries.size(); positionCounter++) {
-                final ViewEntry entry = mAllEntries.get(positionCounter);
-
-                // Ignoring cases where entry is not a detail entry
-                if (entry.getViewType() != ViewAdapter.VIEW_TYPE_DETAIL_ENTRY) continue;
-
-                final DetailViewEntry checkEntry = (DetailViewEntry) entry;
-                if (positionCounter != info.position &&
-                        checkEntry.mimetype.equalsIgnoreCase(selectedMimeType)) {
-                    isUniqueMimeType = false;
-                    break;
-                }
-            }
-
-            // Checking for previously set default
-            if (selectedEntry.isPrimary) {
-                menu.add(ContextMenu.NONE, ContextMenuIds.CLEAR_DEFAULT,
-                        ContextMenu.NONE, getString(R.string.clear_default));
-            } else if (!isUniqueMimeType) {
-                menu.add(ContextMenu.NONE, ContextMenuIds.SET_DEFAULT,
-                        ContextMenu.NONE, getString(R.string.set_default));
-            }
+        // Checking for previously set default
+        if (selectedEntry.isPrimary) {
+            menu.add(ContextMenu.NONE, ContextMenuIds.CLEAR_DEFAULT,
+                    ContextMenu.NONE, getString(R.string.clear_default));
+        } else if (!isUniqueMimeType) {
+            menu.add(ContextMenu.NONE, ContextMenuIds.SET_DEFAULT,
+                    ContextMenu.NONE, getString(R.string.set_default));
         }
     }
 
diff --git a/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java b/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
index eb1d1f0..561d44e 100644
--- a/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
+++ b/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
@@ -66,7 +66,6 @@
     private static final float MAX_ALPHA = 0.5f;
 
     private final Handler mHandler = new Handler();
-    private boolean mAttachedToWindow;
 
     public ContactDetailFragmentCarousel(Context context) {
         this(context, null);
@@ -105,7 +104,8 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    if (mAttachedToWindow && mAboutFragment != null && mUpdatesFragment != null) {
+                    if (isAttachedToWindow() && mAboutFragment != null &&
+                            mUpdatesFragment != null) {
                         snapToEdge();
                     }
                 }
@@ -116,7 +116,7 @@
     public void setCurrentPage(int pageIndex) {
         if (mCurrentPage != pageIndex) {
             mCurrentPage = pageIndex;
-            if (mAttachedToWindow && mAboutFragment != null && mUpdatesFragment != null) {
+            if (isAttachedToWindow() && mAboutFragment != null && mUpdatesFragment != null) {
                 snapToEdge();
             }
         }
@@ -223,15 +223,7 @@
         return false;
     }
 
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        mAttachedToWindow = true;
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        mAttachedToWindow = false;
+    private boolean isAttachedToWindow() {
+        return getWindowToken() != null;
     }
 }
diff --git a/src/com/android/contacts/detail/ContactDetailLayoutController.java b/src/com/android/contacts/detail/ContactDetailLayoutController.java
index 9b56dde..7abe76e 100644
--- a/src/com/android/contacts/detail/ContactDetailLayoutController.java
+++ b/src/com/android/contacts/detail/ContactDetailLayoutController.java
@@ -17,16 +17,18 @@
 package com.android.contacts.detail;
 
 import com.android.contacts.ContactLoader;
+import com.android.contacts.R;
 import com.android.contacts.activities.PeopleActivity.ContactDetailFragmentListener;
 
-import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
+import android.content.Context;
 import android.os.Bundle;
-import android.support.v13.app.FragmentPagerAdapter;
 import android.support.v4.view.ViewPager;
 import android.support.v4.view.ViewPager.OnPageChangeListener;
+import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.AbsListView;
 import android.widget.AbsListView.OnScrollListener;
 
@@ -37,94 +39,146 @@
 
     public static final int FRAGMENT_COUNT = 2;
 
-    private static final String KEY_DETAIL_FRAGMENT_TAG = "detailFragTag";
-    private static final String KEY_UPDATES_FRAGMENT_TAG = "updatesFragTag";
-
-    private String mDetailFragmentTag;
-    private String mUpdatesFragmentTag;
+    private static final String KEY_CONTACT_HAS_UPDATES = "contactHasUpdates";
 
     private enum LayoutMode {
         TWO_COLUMN, VIEW_PAGER_AND_CAROUSEL,
     }
 
+    private final LayoutInflater mLayoutInflater;
     private final FragmentManager mFragmentManager;
 
-    private ContactDetailFragment mContactDetailFragment;
-    private ContactDetailUpdatesFragment mContactDetailUpdatesFragment;
+    private ContactDetailFragment mDetailFragment;
+    private ContactDetailUpdatesFragment mUpdatesFragment;
+
+    private View mDetailFragmentView;
+    private View mUpdatesFragmentView;
 
     private final ViewPager mViewPager;
     private final ContactDetailTabCarousel mTabCarousel;
-    private ContactDetailFragment mPagerContactDetailFragment;
-    private ContactDetailUpdatesFragment mPagerContactDetailUpdatesFragment;
+    private ContactDetailViewPagerAdapter mViewPagerAdapter;
 
     private ContactDetailFragmentListener mContactDetailFragmentListener;
 
     private ContactLoader.Result mContactData;
 
-    private boolean mIsInitialized;
+    private boolean mContactHasUpdates;
 
     private LayoutMode mLayoutMode;
 
-    public ContactDetailLayoutController(FragmentManager fragmentManager, ViewPager viewPager,
-            ContactDetailTabCarousel tabCarousel, ContactDetailFragmentListener
+    public ContactDetailLayoutController(Context context, Bundle savedState,
+            FragmentManager fragmentManager, View viewContainer, ContactDetailFragmentListener
             contactDetailFragmentListener) {
+
         if (fragmentManager == null) {
             throw new IllegalStateException("Cannot initialize a ContactDetailLayoutController "
                     + "without a non-null FragmentManager");
         }
 
+        mLayoutInflater = (LayoutInflater) context.getSystemService(
+                Context.LAYOUT_INFLATER_SERVICE);
         mFragmentManager = fragmentManager;
-        mViewPager = viewPager;
-        mTabCarousel = tabCarousel;
         mContactDetailFragmentListener = contactDetailFragmentListener;
 
-        // Determine the layout based on whether the {@link ViewPager} is null or not. If the
+        // Retrieve views in case this is view pager and carousel mode
+        mViewPager = (ViewPager) viewContainer.findViewById(R.id.pager);
+        mTabCarousel = (ContactDetailTabCarousel) viewContainer.findViewById(R.id.tab_carousel);
+
+        // Retrieve views in case this is 2-column layout mode
+        mDetailFragmentView = viewContainer.findViewById(R.id.about_fragment_container);
+        mUpdatesFragmentView = viewContainer.findViewById(R.id.updates_fragment_container);
+
+        // Determine the layout mode based on whether the {@link ViewPager} is null or not. If the
         // {@link ViewPager} is null, then this is a wide screen and the content can be displayed
         // in 2 columns side by side. If the {@link ViewPager} is non-null, then this is a narrow
         // screen and the user will need to swipe to see all the data.
         mLayoutMode = (mViewPager == null) ? LayoutMode.TWO_COLUMN :
                 LayoutMode.VIEW_PAGER_AND_CAROUSEL;
 
+        initialize(savedState);
     }
 
-    public boolean isInitialized() {
-        return mIsInitialized;
-    }
+    private void initialize(Bundle savedState) {
+        boolean fragmentsAddedToFragmentManager = true;
+        mDetailFragment = (ContactDetailFragment) mFragmentManager.findFragmentByTag(
+                ContactDetailViewPagerAdapter.ABOUT_FRAGMENT_TAG);
+        mUpdatesFragment = (ContactDetailUpdatesFragment) mFragmentManager.findFragmentByTag(
+                ContactDetailViewPagerAdapter.UPDTES_FRAGMENT_TAG);
 
-    public void initialize() {
-        mIsInitialized = true;
-        if (mDetailFragmentTag != null || mUpdatesFragmentTag != null) {
-            // Manually remove any {@link ViewPager} fragments if there was an orientation change
-            ContactDetailFragment oldDetailFragment = (ContactDetailFragment) mFragmentManager.
-                    findFragmentByTag(mDetailFragmentTag);
-            ContactDetailUpdatesFragment oldUpdatesFragment = (ContactDetailUpdatesFragment)
-                    mFragmentManager.findFragmentByTag(mUpdatesFragmentTag);
+        // If the detail fragment was found in the {@link FragmentManager} then we don't need to add
+        // it again. Otherwise, create the fragments dynamically and remember to add them to the
+        // {@link FragmentManager}.
+        if (mDetailFragment == null) {
+            mDetailFragment = new ContactDetailFragment();
+            mUpdatesFragment = new ContactDetailUpdatesFragment();
+            fragmentsAddedToFragmentManager = false;
+        }
 
-            if (oldDetailFragment != null && oldUpdatesFragment != null) {
-                FragmentTransaction ft = mFragmentManager.beginTransaction();
-                ft.remove(oldDetailFragment);
-                ft.remove(oldUpdatesFragment);
-                ft.commitAllowingStateLoss();
+        mDetailFragment.setListener(mContactDetailFragmentListener);
+        mDetailFragment.setVerticalScrollListener(mVerticalScrollListener);
+        mUpdatesFragment.setVerticalScrollListener(mVerticalScrollListener);
+
+        switch (mLayoutMode) {
+            case VIEW_PAGER_AND_CAROUSEL: {
+                mTabCarousel.setListener(mTabCarouselListener);
+                // Inflate 2 view containers to pass in as children to the {@link ViewPager},
+                // which will in turn be the parents to the mDetailFragment and mUpdatesFragment
+                // since the fragments must have the same parent view IDs in both landscape and
+                // portrait layouts.
+                ViewGroup detailContainer = (ViewGroup) mLayoutInflater.inflate(
+                        R.layout.contact_detail_about_fragment_container, mViewPager, false);
+                ViewGroup updatesContainer = (ViewGroup) mLayoutInflater.inflate(
+                        R.layout.contact_detail_updates_fragment_container, mViewPager, false);
+
+                mViewPagerAdapter = new ContactDetailViewPagerAdapter();
+                mViewPagerAdapter.setAboutFragmentView(detailContainer);
+                mViewPagerAdapter.setUpdatesFragmentView(updatesContainer);
+
+                mViewPager.addView(detailContainer);
+                mViewPager.addView(updatesContainer);
+                mViewPager.setAdapter(mViewPagerAdapter);
+                mViewPager.setOnPageChangeListener(mOnPageChangeListener);
+
+                FragmentTransaction transaction = mFragmentManager.beginTransaction();
+                if (!fragmentsAddedToFragmentManager) {
+                    transaction.add(R.id.about_fragment_container, mDetailFragment,
+                            ContactDetailViewPagerAdapter.ABOUT_FRAGMENT_TAG);
+                    transaction.add(R.id.updates_fragment_container, mUpdatesFragment,
+                            ContactDetailViewPagerAdapter.UPDTES_FRAGMENT_TAG);
+                } else {
+                    transaction.show(mDetailFragment);
+                    transaction.show(mUpdatesFragment);
+                }
+                transaction.commit();
+                mFragmentManager.executePendingTransactions();
+                break;
+            }
+            case TWO_COLUMN: {
+                if (!fragmentsAddedToFragmentManager) {
+                    FragmentTransaction transaction = mFragmentManager.beginTransaction();
+                    transaction.add(R.id.about_fragment_container, mDetailFragment,
+                            ContactDetailViewPagerAdapter.ABOUT_FRAGMENT_TAG);
+                    transaction.add(R.id.updates_fragment_container, mUpdatesFragment,
+                            ContactDetailViewPagerAdapter.UPDTES_FRAGMENT_TAG);
+                    transaction.commit();
+                    mFragmentManager.executePendingTransactions();
+                }
             }
         }
-        if (mViewPager != null) {
-            mViewPager.setAdapter(new ViewPagerAdapter(mFragmentManager));
-            mViewPager.setOnPageChangeListener(mOnPageChangeListener);
-            mTabCarousel.setListener(mTabCarouselListener);
+
+        if (savedState != null) {
+            if (savedState.getBoolean(KEY_CONTACT_HAS_UPDATES)) {
+                showContactWithUpdates();
+            } else {
+                showContactWithoutUpdates();
+            }
         }
     }
 
-    public void setContactDetailFragment(ContactDetailFragment contactDetailFragment) {
-        mContactDetailFragment = contactDetailFragment;
-    }
-
-    public void setContactDetailUpdatesFragment(ContactDetailUpdatesFragment updatesFragment) {
-        mContactDetailUpdatesFragment = updatesFragment;
-    }
-
     public void setContactData(ContactLoader.Result data) {
         mContactData = data;
-        if (!data.getStreamItems().isEmpty()) {
+        mContactHasUpdates = !data.getStreamItems().isEmpty();
+        if (mContactHasUpdates) {
             showContactWithUpdates();
         } else {
             showContactWithoutUpdates();
@@ -132,117 +186,59 @@
     }
 
     private void showContactWithUpdates() {
-        FragmentTransaction ft = mFragmentManager.beginTransaction();
-
         switch (mLayoutMode) {
             case TWO_COLUMN: {
                 // Set the contact data (hide the static photo because the photo will already be in
                 // the header that scrolls with contact details).
-                mContactDetailFragment.setShowStaticPhoto(false);
-                mContactDetailFragment.setData(mContactData.getLookupUri(), mContactData);
-                mContactDetailUpdatesFragment.setData(mContactData.getLookupUri(), mContactData);
-
-                // Update fragment visibility
-                ft.show(mContactDetailUpdatesFragment);
+                mDetailFragment.setShowStaticPhoto(false);
+                // Show the updates fragment
+                mUpdatesFragmentView.setVisibility(View.VISIBLE);
                 break;
             }
             case VIEW_PAGER_AND_CAROUSEL: {
-                // Set the contact data
+                // Update and show the tab carousel
                 mTabCarousel.loadData(mContactData);
-                mPagerContactDetailFragment.setData(mContactData.getLookupUri(), mContactData);
-                mPagerContactDetailUpdatesFragment.setData(mContactData.getLookupUri(),
-                        mContactData);
-
-                // Update fragment and view visibility
-                mViewPager.setVisibility(View.VISIBLE);
                 mTabCarousel.setVisibility(View.VISIBLE);
-                ft.hide(mContactDetailFragment);
+                // Update ViewPager so that it has the max # of tabs (to show updates)
+                mViewPagerAdapter.setFragmentViewCount(FRAGMENT_COUNT);
                 break;
             }
             default:
                 throw new IllegalStateException("Invalid LayoutMode " + mLayoutMode);
         }
 
-        // If the activity has already saved its state, then allow this fragment
-        // transaction to be dropped because there's nothing else we can do to update the UI.
-        // The fact that the contact URI has already been saved by the activity means we can
-        // restore this later.
-        ft.commitAllowingStateLoss();
+        if (mContactData != null) {
+            mDetailFragment.setData(mContactData.getLookupUri(), mContactData);
+            mUpdatesFragment.setData(mContactData.getLookupUri(), mContactData);
+        }
     }
 
     private void showContactWithoutUpdates() {
-        FragmentTransaction ft = mFragmentManager.beginTransaction();
-
         switch (mLayoutMode) {
             case TWO_COLUMN:
-                mContactDetailFragment.setShowStaticPhoto(true);
-                mContactDetailFragment.setData(mContactData.getLookupUri(), mContactData);
-                ft.hide(mContactDetailUpdatesFragment);
+                // Show the static photo which is next to the list of scrolling contact details
+                mDetailFragment.setShowStaticPhoto(true);
+                // Hide the updates fragment
+                mUpdatesFragmentView.setVisibility(View.GONE);
                 break;
             case VIEW_PAGER_AND_CAROUSEL:
-                mContactDetailFragment.setData(mContactData.getLookupUri(), mContactData);
-                ft.show(mContactDetailFragment);
-                mViewPager.setVisibility(View.GONE);
+                // Hide the tab carousel
                 mTabCarousel.setVisibility(View.GONE);
+                // Update ViewPager so that it only has 1 tab and switch to the first indexed tab
+                mViewPagerAdapter.setFragmentViewCount(1);
+                mViewPager.setCurrentItem(0);
                 break;
             default:
                 throw new IllegalStateException("Invalid LayoutMode " + mLayoutMode);
         }
 
-        // If the activity has already saved its state, then allow this fragment
-        // transaction to be dropped because there's nothing else we can do to update the UI.
-        // The fact that the contact URI has already been saved by the activity means we can
-        // restore this later.
-        ft.commitAllowingStateLoss();
+        if (mContactData != null) {
+            mDetailFragment.setData(mContactData.getLookupUri(), mContactData);
+        }
     }
 
     public void onSaveInstanceState(Bundle outState) {
-        if (mPagerContactDetailFragment != null) {
-            outState.putString(KEY_DETAIL_FRAGMENT_TAG,
-                    mPagerContactDetailFragment.getTag());
-            outState.putString(KEY_UPDATES_FRAGMENT_TAG,
-                    mPagerContactDetailUpdatesFragment.getTag());
-        }
-    }
-
-    public void onRestoreInstanceState(Bundle savedState) {
-        mDetailFragmentTag = savedState.getString(KEY_DETAIL_FRAGMENT_TAG);
-        mUpdatesFragmentTag = savedState.getString(KEY_UPDATES_FRAGMENT_TAG);
-    }
-
-    public class ViewPagerAdapter extends FragmentPagerAdapter{
-
-        public ViewPagerAdapter(FragmentManager fm) {
-            super(fm);
-        }
-
-        @Override
-        public Fragment getItem(int position) {
-            switch (position) {
-                case 0:
-                    mPagerContactDetailFragment = new ContactDetailFragment();
-                    if (mContactData != null) {
-                        mPagerContactDetailFragment.setData(mContactData.getLookupUri(),
-                                mContactData);
-                    }
-                    mPagerContactDetailFragment.setListener(mContactDetailFragmentListener);
-                    mPagerContactDetailFragment.setVerticalScrollListener(mVerticalScrollListener);
-                    return mPagerContactDetailFragment;
-                case 1:
-                    mPagerContactDetailUpdatesFragment = new ContactDetailUpdatesFragment();
-                    if (mContactData != null) {
-                        mPagerContactDetailUpdatesFragment.setData(mContactData.getLookupUri(),
-                                mContactData);
-                    }
-                    return mPagerContactDetailUpdatesFragment;
-            }
-            throw new IllegalStateException("No fragment at position " + position);
-        }
-
-        @Override
-        public int getCount() {
-            return FRAGMENT_COUNT;
-        }
+        outState.putBoolean(KEY_CONTACT_HAS_UPDATES, mContactHasUpdates);
     }
 
     private OnPageChangeListener mOnPageChangeListener = new OnPageChangeListener() {
diff --git a/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java b/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
index d668429..308254f 100644
--- a/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
@@ -21,7 +21,7 @@
 import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
 import com.android.contacts.util.StreamItemEntry;
 
-import android.app.Fragment;
+import android.app.ListFragment;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
@@ -30,10 +30,10 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
-import android.widget.LinearLayout;
+import android.widget.AbsListView.OnScrollListener;
 import android.widget.TextView;
 
-public class ContactDetailUpdatesFragment extends Fragment
+public class ContactDetailUpdatesFragment extends ListFragment
         implements FragmentKeyListener, ViewOverlay {
 
     private static final String TAG = "ContactDetailUpdatesFragment";
@@ -42,9 +42,7 @@
     private Uri mLookupUri;
 
     private LayoutInflater mInflater;
-
-    // The linear layout that contains all the stream items.
-    private LinearLayout mStreamContainer;
+    private StreamItemAdapter mStreamItemAdapter;
 
     /**
      * This optional view adds an alpha layer over the entire fragment.
@@ -57,12 +55,14 @@
      */
     private View mTouchInterceptLayer;
 
+    private OnScrollListener mVerticalScrollListener;
+
     /**
      * Listener on clicks on a stream item.
      * <p>
      * It assumes the view has a tag of type {@link StreamItemEntry} associated with it.
      */
-    private View.OnClickListener mStreamItemClickListener = new OnClickListener() {
+    private View.OnClickListener mStreamItemClickListener = new View.OnClickListener() {
         @Override
         public void onClick(View view) {
             StreamItemEntry streamItemEntry = (StreamItemEntry) view.getTag();
@@ -90,17 +90,8 @@
                 false);
 
         TextView titleTextView = (TextView) rootView.findViewById(R.id.kind);
-        titleTextView.setText(getString(R.string.recent_updates).toUpperCase());
-
-        mStreamContainer = (LinearLayout) rootView.findViewById(R.id.update_list);
-
-        // It is possible that the contact data was set to the fragment when it was first attached
-        // to the activity, but before this method was called because the fragment was not
-        // visible on screen yet (i.e. using a {@link ViewPager}), so display the data if we already
-        // have it.
-        if (mContactData != null) {
-            ContactDetailDisplayUtils.showSocialStreamItems(inflater, getActivity(), mContactData,
-                    mStreamContainer, mStreamItemClickListener);
+        if (titleTextView != null) {
+            titleTextView.setText(getString(R.string.recent_updates).toUpperCase());
         }
 
         mAlphaLayer = rootView.findViewById(R.id.alpha_overlay);
@@ -109,14 +100,29 @@
         return rootView;
     }
 
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        mStreamItemAdapter = new StreamItemAdapter(getActivity(), mStreamItemClickListener);
+        setListAdapter(mStreamItemAdapter);
+        getListView().setOnScrollListener(mVerticalScrollListener);
+
+        // It is possible that the contact data was set to the fragment when it was first attached
+        // to the activity, but before this method was called because the fragment was not
+        // visible on screen yet (i.e. using a {@link ViewPager}), so display the data if we already
+        // have it.
+        if (mContactData != null) {
+            mStreamItemAdapter.setStreamItems(mContactData.getStreamItems());
+        }
+    }
+
     public void setData(Uri lookupUri, ContactLoader.Result result) {
         if (result == null) {
             return;
         }
         mLookupUri = lookupUri;
         mContactData = result;
-        ContactDetailDisplayUtils.showSocialStreamItems(mInflater, getActivity(), mContactData,
-                mStreamContainer, mStreamItemClickListener);
+        mStreamItemAdapter.setStreamItems(mContactData.getStreamItems());
     }
 
     @Override
@@ -152,4 +158,9 @@
     public boolean handleKeyDown(int keyCode) {
         return false;
     }
+
+    public void setVerticalScrollListener(OnScrollListener listener) {
+        mVerticalScrollListener = listener;
+    }
+
 }
diff --git a/src/com/android/contacts/detail/ContactDetailViewPagerAdapter.java b/src/com/android/contacts/detail/ContactDetailViewPagerAdapter.java
index 39544df..d7f2743 100644
--- a/src/com/android/contacts/detail/ContactDetailViewPagerAdapter.java
+++ b/src/com/android/contacts/detail/ContactDetailViewPagerAdapter.java
@@ -29,11 +29,13 @@
     public static final String ABOUT_FRAGMENT_TAG = "view-pager-about-fragment";
     public static final String UPDTES_FRAGMENT_TAG = "view-pager-updates-fragment";
 
-    private static final int FRAGMENT_COUNT = 2;
-
     private static final int INDEX_ABOUT_FRAGMENT = 0;
     private static final int INDEX_UPDATES_FRAGMENT = 1;
 
+    private static final int MAX_FRAGMENT_VIEW_COUNT = 2;
+
+    private int mFragmentViewCount = MAX_FRAGMENT_VIEW_COUNT;
+
     private ViewGroup mAboutFragmentView;
     private ViewGroup mUpdatesFragmentView;
 
@@ -48,9 +50,18 @@
         mUpdatesFragmentView = view;
     }
 
+    public void setFragmentViewCount(int viewCount) {
+        if (viewCount < 0 || viewCount > MAX_FRAGMENT_VIEW_COUNT) {
+            throw new IllegalStateException("The view count in the ViewPager adapter must not be"
+                    + "less than 0 or exceed " + MAX_FRAGMENT_VIEW_COUNT);
+        }
+        mFragmentViewCount = viewCount;
+        notifyDataSetChanged();
+    }
+
     @Override
     public int getCount() {
-        return FRAGMENT_COUNT;
+        return mFragmentViewCount;
     }
 
     /** Gets called when the number of items changes. */
diff --git a/src/com/android/contacts/detail/StreamItemAdapter.java b/src/com/android/contacts/detail/StreamItemAdapter.java
new file mode 100644
index 0000000..d8f4a81
--- /dev/null
+++ b/src/com/android/contacts/detail/StreamItemAdapter.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.contacts.detail;
+
+import com.android.contacts.R;
+import com.android.contacts.util.StreamItemEntry;
+import com.google.android.collect.Lists;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+import java.util.List;
+
+/**
+ * List adapter for stream items of a given contact.
+ */
+public class StreamItemAdapter extends BaseAdapter {
+    private static final int ITEM_VIEW_TYPE_HEADER = 0;
+    private static final int ITEM_VIEW_TYPE_STREAM_ITEM = 1;
+
+    private final Context mContext;
+    private final View.OnClickListener mListener;
+    private final LayoutInflater mInflater;
+
+    private List<StreamItemEntry> mStreamItems;
+
+    public StreamItemAdapter(Context context, View.OnClickListener listener) {
+        mContext = context;
+        mListener = listener;
+        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        mStreamItems = Lists.newArrayList();
+    }
+
+    @Override
+    public int getCount() {
+        return mStreamItems.size() + 1;
+    }
+
+    @Override
+    public Object getItem(int position) {
+        if (position == 0) {
+            return null;
+        }
+        return mStreamItems.get(position - 1);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        if (position == 0) {
+            return -1;
+        }
+        return position - 1;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        if (position == 0) {
+            return mInflater.inflate(R.layout.updates_header_contact, null);
+        }
+        return ContactDetailDisplayUtils.addStreamItemToContainer(
+                mInflater, mContext, (StreamItemEntry) getItem(position), null, mListener);
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        if (position == 0) {
+            return ITEM_VIEW_TYPE_HEADER;
+        }
+        return ITEM_VIEW_TYPE_STREAM_ITEM;
+    }
+
+    public void setStreamItems(List<StreamItemEntry> streamItems) {
+        mStreamItems = streamItems;
+        notifyDataSetChanged();
+    }
+}
diff --git a/src/com/android/contacts/list/ContactTileAdapter.java b/src/com/android/contacts/list/ContactTileAdapter.java
index 5850a4a..0d4eb8c 100644
--- a/src/com/android/contacts/list/ContactTileAdapter.java
+++ b/src/com/android/contacts/list/ContactTileAdapter.java
@@ -365,8 +365,12 @@
         View dividerView = View.inflate(mContext, R.layout.list_separator, null);
         dividerView.setFocusable(false);
         TextView text = (TextView) dividerView.findViewById(R.id.header_text);
-        text.setText(mContext.getString(R.string.favoritesFrquentSeparator));
-        return dividerView;
+
+        text.setText(mDisplayType == DisplayType.STREQUENT_PHONE_ONLY ?
+                mContext.getString(R.string.favoritesFrequentCalled) :
+                mContext.getString(R.string.favoritesFrequentContacted));
+
+       return dividerView;
     }
 
     private int getLayoutResourceId(int viewType) {
diff --git a/src/com/android/contacts/list/CustomContactListFilterActivity.java b/src/com/android/contacts/list/CustomContactListFilterActivity.java
index ae21824..e0965cc 100644
--- a/src/com/android/contacts/list/CustomContactListFilterActivity.java
+++ b/src/com/android/contacts/list/CustomContactListFilterActivity.java
@@ -128,12 +128,14 @@
                 AccountDisplay accountDisplay =
                         new AccountDisplay(resolver, account.name, account.type, account.dataSet);
 
-                final Uri groupsUri = Groups.CONTENT_URI.buildUpon()
+                final Uri.Builder groupsUri = Groups.CONTENT_URI.buildUpon()
                         .appendQueryParameter(Groups.ACCOUNT_NAME, account.name)
-                        .appendQueryParameter(Groups.ACCOUNT_TYPE, account.type)
-                        .appendQueryParameter(Groups.DATA_SET, account.dataSet).build();
+                        .appendQueryParameter(Groups.ACCOUNT_TYPE, account.type);
+                if (account.dataSet != null) {
+                    groupsUri.appendQueryParameter(Groups.DATA_SET, account.dataSet).build();
+                }
                 EntityIterator iterator = ContactsContract.Groups.newEntityIterator(resolver.query(
-                        groupsUri, null, null, null, null));
+                        groupsUri.build(), null, null, null, null));
                 try {
                     boolean hasGroups = false;
 
diff --git a/src/com/android/contacts/quickcontact/DataAction.java b/src/com/android/contacts/quickcontact/DataAction.java
index 6f719af..827016f 100644
--- a/src/com/android/contacts/quickcontact/DataAction.java
+++ b/src/com/android/contacts/quickcontact/DataAction.java
@@ -2,8 +2,9 @@
 
 import com.android.contacts.ContactsUtils;
 import com.android.contacts.R;
-import com.android.contacts.model.DataKind;
 import com.android.contacts.model.AccountType.EditType;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.DataKind;
 import com.android.contacts.util.Constants;
 import com.android.contacts.util.PhoneCapabilityTester;
 
@@ -15,12 +16,12 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.net.WebAddress;
-import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.Im;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.CommonDataKinds.SipAddress;
 import android.provider.ContactsContract.CommonDataKinds.Website;
+import android.provider.ContactsContract.Data;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -142,13 +143,12 @@
                 mIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(webAddress.toString()));
             }
 
-        } else if (Im.CONTENT_ITEM_TYPE.equals(mimeType)
-                || Constants.MIME_TYPE_VIDEO_CHAT.equals(mimeType)) {
+        } else if (Im.CONTENT_ITEM_TYPE.equals(mimeType)) {
             final boolean isEmail = Email.CONTENT_ITEM_TYPE.equals(
                     getAsString(cursor, Data.MIMETYPE));
             if (isEmail || isProtocolValid(cursor)) {
                 final int protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK :
-                    getAsInt(cursor, Im.PROTOCOL);
+                        getAsInt(cursor, Im.PROTOCOL);
 
                 if (isEmail) {
                     // Use Google Talk string when using Email, and clear data
@@ -165,17 +165,29 @@
                     host = ContactsUtils.lookupProviderNameFromId(protocol);
                 }
 
-                if (Constants.MIME_TYPE_VIDEO_CHAT.equals(mimeType)) {
-                    if (!TextUtils.isEmpty(data)) {
-                        mIntent = new Intent(Intent.ACTION_SENDTO);
-                        mIntent.setDataAndType(Uri.parse("xmpp:" + data + "?call"),
-                                Constants.MIME_TYPE_VIDEO_CHAT);
-                    }
-                } else if (!TextUtils.isEmpty(host) && !TextUtils.isEmpty(data)) {
+                if (!TextUtils.isEmpty(host) && !TextUtils.isEmpty(data)) {
                     final String authority = host.toLowerCase();
                     final Uri imUri = new Uri.Builder().scheme(Constants.SCHEME_IMTO).authority(
                             authority).appendPath(data).build();
                     mIntent = new Intent(Intent.ACTION_SENDTO, imUri);
+
+                    // If the address is also available for a video chat, we'll show the capability
+                    // as a secondary action.
+                    final int chatCapability = getAsInt(cursor, Data.CHAT_CAPABILITY);
+                    final boolean isVideoChatCapable =
+                            (chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0;
+                    final boolean isAudioChatCapable =
+                            (chatCapability & Im.CAPABILITY_HAS_VOICE) != 0;
+                    if (isVideoChatCapable || isAudioChatCapable) {
+                        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(
+                                context.getApplicationContext());
+                        mAlternateIntent = new Intent(
+                                Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?call"));
+                        // Use Holo dark theme since the background is darker than usual.
+                        mAlternateIconRes = (isVideoChatCapable
+                                ? R.drawable.sym_action_videochat_holo_dark
+                                : R.drawable.sym_action_audiochat_holo_dark);
+                    }
                 }
             }
         }
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 1ef40db..d8f9c2c 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -467,8 +467,6 @@
                 }
             }
 
-            boolean isIm = Im.CONTENT_ITEM_TYPE.equals(mimeType);
-
             // Handle Email rows with presence data as Im entry
             final boolean hasPresence = !cursor.isNull(DataQuery.PRESENCE);
             if (hasPresence && Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
@@ -478,20 +476,6 @@
                     final DataAction action = new DataAction(context, Im.CONTENT_ITEM_TYPE, imKind,
                             dataId, cursor);
                     considerAdd(action, cache);
-                    isIm = true;
-                }
-            }
-
-            if (hasPresence && isIm) {
-                int chatCapability = cursor.getInt(DataQuery.CHAT_CAPABILITY);
-                if ((chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0) {
-                    final DataKind imKind = accountTypes.getKindOrFallback(accountType, dataSet,
-                            Im.CONTENT_ITEM_TYPE);
-                    if (imKind != null) {
-                        final DataAction chatAction = new DataAction(context,
-                                Constants.MIME_TYPE_VIDEO_CHAT, imKind, dataId, cursor);
-                        considerAdd(chatAction, cache);
-                    }
                 }
             }
         }
diff --git a/tests/src/com/android/contacts/CallDetailActivityTest.java b/tests/src/com/android/contacts/CallDetailActivityTest.java
index cdb6e44..7e225c4 100644
--- a/tests/src/com/android/contacts/CallDetailActivityTest.java
+++ b/tests/src/com/android/contacts/CallDetailActivityTest.java
@@ -30,6 +30,7 @@
 import android.provider.CallLog;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.Suppress;
 import android.view.Menu;
 import android.widget.TextView;
 
@@ -79,6 +80,7 @@
      * then click the play button (which just reported an error), then after that try to adjust the
      * rate.  See http://b/5047879.
      */
+    @Suppress
     public void testClickIncreaseRateButtonWithInvalidVoicemailDoesNotCrash() throws Throwable {
         setActivityIntentForTestVoicemailEntry();
         Activity activity = getActivity();
@@ -87,6 +89,7 @@
     }
 
     /** Test for bug where missing Extras on intent used to start Activity causes NPE. */
+    @Suppress
     public void testCallLogUriWithMissingExtrasShouldNotCauseNPE() throws Exception {
         setActivityIntentForTestCallEntry();
         getActivity();
@@ -97,6 +100,7 @@
      * <p>
      * See http://b/5054103.
      */
+    @Suppress
     public void testVoicemailDoesNotHaveRemoveFromCallLog() throws Throwable {
         setActivityIntentForTestVoicemailEntry();
         CallDetailActivity activity = getActivity();
@@ -121,6 +125,7 @@
      * <p>
      * See bug http://b/5044075.
      */
+    @Suppress
     public void testVoicemailPlaybackRateDisplayedOnUi() throws Throwable {
         setActivityIntentForTestVoicemailEntry();
         CallDetailActivity activity = getActivity();