Filter and header refactoring.

- have AccountFilterUtil to unify account filter implementations.
- modify account header on top of search screens
  Now it is bigger than before (40dip > 32dip), and uses people's
  blue text color instead of gray (issue 5451033)
- introduce ContactListSeparatorTextViewStyle and use it everywhere

Bug: 5269692
Bug: 5451033
Bug: 5429203
Change-Id: Ibe810ff9adaafc74d53b0dcf171a3853f4be039a
diff --git a/res/layout-sw580dp/list_separator.xml b/res/layout-sw580dp/list_separator.xml
index a53bd6b..34e8d79 100644
--- a/res/layout-sw580dp/list_separator.xml
+++ b/res/layout-sw580dp/list_separator.xml
@@ -17,12 +17,6 @@
 <TextView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/title"
-    style="?android:attr/listSeparatorTextViewStyle"
-    android:layout_height="32dip"
+    style="@style/ContactListSeparatorTextViewStyle"
     android:paddingLeft="8dip"
-    android:paddingRight="8dip"
-    android:background="@drawable/list_section_divider_holo_custom"
-    android:textColor="@color/people_app_theme_color"
-    android:textAllCaps="true"
-    android:singleLine="true"
-    android:ellipsize="end" />
\ No newline at end of file
+    android:paddingRight="8dip" />
diff --git a/res/layout/account_filter_header.xml b/res/layout/account_filter_header.xml
index 4d45d25..26207f0 100644
--- a/res/layout/account_filter_header.xml
+++ b/res/layout/account_filter_header.xml
@@ -22,7 +22,6 @@
     android:id="@+id/account_filter_header_container"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:minHeight="?attr/list_item_header_height"
     android:orientation="vertical"
     android:paddingTop="@dimen/contact_browser_list_top_margin"
     android:layout_marginLeft="@dimen/contact_browser_list_header_left_margin"
@@ -31,17 +30,6 @@
     android:visibility="gone">
     <TextView
         android:id="@+id/account_filter_header"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:singleLine="true"
-        android:ellipsize="end"
-        android:textStyle="bold"
-        android:textAllCaps="true"
-        android:paddingLeft="@dimen/contact_browser_list_item_text_indent"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-        android:textColor="?android:attr/textColorSecondary" />
-    <View
-        android:id="@+id/account_filter_header_bottom_divider"
-        android:layout_height="1dip"
-        style="@style/SectionDivider" />
+        style="@style/ContactListSeparatorTextViewStyle"
+        android:paddingLeft="@dimen/contact_browser_list_item_text_indent" />
 </LinearLayout>
diff --git a/res/layout/call_log_list_item.xml b/res/layout/call_log_list_item.xml
index 4768bf6..777c7af 100644
--- a/res/layout/call_log_list_item.xml
+++ b/res/layout/call_log_list_item.xml
@@ -129,20 +129,11 @@
 
     <TextView
         android:id="@+id/call_log_header"
-        style="?android:attr/listSeparatorTextViewStyle"
+        style="@style/ContactListSeparatorTextViewStyle"
         android:layout_marginLeft="@dimen/call_log_outer_margin"
         android:layout_marginRight="@dimen/call_log_outer_margin"
         android:paddingTop="@dimen/call_log_inner_margin"
-        android:paddingBottom="@dimen/call_log_inner_margin"
-        android:background="@drawable/list_section_divider_holo_custom"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-        android:textStyle="bold"
-        android:textColor="?attr/call_log_header_color"
-        android:textAllCaps="true"
-        android:singleLine="true"
-        android:ellipsize="end"
-        android:focusable="true"
-    />
+        android:paddingBottom="@dimen/call_log_inner_margin" />
 
     <View
         android:id="@+id/call_log_divider"
diff --git a/res/layout/contacts_list_content.xml b/res/layout/contact_list_content.xml
similarity index 100%
rename from res/layout/contacts_list_content.xml
rename to res/layout/contact_list_content.xml
diff --git a/res/layout/directory_header.xml b/res/layout/directory_header.xml
index a1516ef..a2adf48 100644
--- a/res/layout/directory_header.xml
+++ b/res/layout/directory_header.xml
@@ -20,7 +20,9 @@
     style="@style/DirectoryHeader"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:minHeight="?attr/list_item_header_height"
+    android:minHeight="@dimen/list_section_divider_min_height"
+    android:background="@drawable/list_section_divider_holo_custom"
+    android:paddingTop="@dimen/contact_browser_list_top_margin"
     android:paddingLeft="?attr/list_item_padding_left"
     android:paddingRight="?attr/list_item_padding_right">
     <TextView
@@ -32,7 +34,7 @@
         android:layout_centerVertical="true"
         android:layout_marginLeft="8dip"
         android:textAppearance="?android:attr/textAppearanceSmall"
-        android:textColor="?android:attr/textColorSecondary"
+        android:textColor="@color/people_app_theme_color"
         android:singleLine="true"
         android:textStyle="bold"
         android:textAllCaps="true" />
@@ -55,12 +57,8 @@
         android:layout_marginLeft="8dip"
         android:layout_marginRight="8dip"
         android:textAppearance="?android:attr/textAppearanceSmall"
-        android:textColor="?android:attr/textColorSecondary"
+        android:textColor="@color/people_app_theme_color"
         android:singleLine="true"
         android:textStyle="bold"
         android:textAllCaps="true" />
-    <View
-        android:id="@+id/contact_filter_header_bottom_divider"
-        style="@style/SectionDivider"
-        android:layout_below="@id/display_name" />
 </RelativeLayout>
diff --git a/res/layout/edit_kind_title.xml b/res/layout/edit_kind_title.xml
index f178876..1cd6833 100644
--- a/res/layout/edit_kind_title.xml
+++ b/res/layout/edit_kind_title.xml
@@ -20,20 +20,13 @@
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="32dip"
+    android:layout_height="wrap_content"
     android:paddingLeft="8dip"
     android:paddingRight="8dip"
     android:focusable="false">
-
     <TextView
         android:id="@+id/kind_title"
-        style="?android:attr/listSeparatorTextViewStyle"
+        style="@style/ContactListSeparatorTextViewStyle"
         android:paddingLeft="8dip"
-        android:paddingRight="8dip"
-        android:background="@drawable/list_section_divider_holo_custom"
-        android:textColor="@color/people_app_theme_color"
-        android:textAllCaps="true"
-        android:singleLine="true"
-        android:ellipsize="end" />
-
-</FrameLayout>
\ No newline at end of file
+        android:paddingRight="8dip" />
+</FrameLayout>
diff --git a/res/layout/list_separator.xml b/res/layout/list_separator.xml
index 3ffaca7..d94e18c 100644
--- a/res/layout/list_separator.xml
+++ b/res/layout/list_separator.xml
@@ -17,20 +17,13 @@
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="32dip"
+    android:layout_height="wrap_content"
     android:paddingLeft="16dip"
     android:paddingRight="16dip"
     android:focusable="false">
-
     <TextView
         android:id="@+id/title"
-        style="?android:attr/listSeparatorTextViewStyle"
+        style="@style/ContactListSeparatorTextViewStyle"
         android:paddingLeft="8dip"
-        android:paddingRight="8dip"
-        android:background="@drawable/list_section_divider_holo_custom"
-        android:textColor="@color/people_app_theme_color"
-        android:textAllCaps="true"
-        android:singleLine="true"
-        android:ellipsize="end" />
-
+        android:paddingRight="8dip" />
 </FrameLayout>
diff --git a/res/layout/phone_favorite_account_filter_header.xml b/res/layout/phone_favorite_account_filter_header.xml
deleted file mode 100644
index d63382a..0000000
--- a/res/layout/phone_favorite_account_filter_header.xml
+++ /dev/null
@@ -1,45 +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.
--->
-
-<!-- Layout showing the type of account filter in phone favorite screen.
-
-     Note: This xml is based on account_filter_header.xml and list_separator.xml.
-     Some configurations (e.g. padding) are from account_filter_header.xml, while
-     some other configurations (e.g. background, height, text style) are from
-     list_separator.xml. See also bug 5432231. -->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/account_filter_header_container"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:minHeight="32dip"
-    android:paddingTop="@dimen/contact_browser_list_top_margin"
-    android:layout_marginLeft="@dimen/contact_browser_list_header_left_margin"
-    android:layout_marginRight="@dimen/contact_browser_list_header_right_margin"
-    android:background="?android:attr/selectableItemBackground"
-    android:visibility="gone">
-    <TextView
-        android:id="@+id/account_filter_header"
-        style="?android:attr/listSeparatorTextViewStyle"
-        android:singleLine="true"
-        android:ellipsize="end"
-        android:textStyle="bold"
-        android:textAllCaps="true"
-        android:textColor="@color/people_app_theme_color"
-        android:paddingLeft="@dimen/contact_browser_list_item_text_indent"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-        android:background="@drawable/list_section_divider_holo_custom" />
-</FrameLayout>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 6c21d31..12ae918 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -214,4 +214,9 @@
     <integer name="dialpad_layout_weight_digits">20</integer>
     <integer name="dialpad_layout_weight_dialpad">65</integer>
     <integer name="dialpad_layout_weight_additional_buttons">15</integer>
+
+    <!-- Minimum height used with @drawable/list_section_divider_holo_custom.
+         Right now the drawable has implicit 32dip minimal height, which is confusing.
+         This value is for making the hidden configuration explicit in xml. -->
+    <dimen name="list_section_divider_min_height">32dip</dimen>
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index c337933..93be77a 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -301,5 +301,27 @@
         <item name="android:background">@color/quickcontact_tab_indicator</item>
     </style>
 
+
     <style name="GroupMembershipSizeTextAppearance" parent="@android:style/TextAppearance.Small"/>
+
+    <!-- TextView style with blue underline. It is most suitable for headers.
+
+         This is similar to ?android:attr/listSeparatorTextView but uses different
+         background and text color. See also android:style/Widget.Holo.TextView.ListSeparator
+         (which is private, so we cannot specify it as a parent style).  -->
+    <style name="ContactListSeparatorTextViewStyle">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">wrap_content</item>
+        <!-- See comments for @dimen/list_section_divider_min_height -->
+        <item name="android:minHeight">@dimen/list_section_divider_min_height</item>
+        <item name="android:background">@drawable/list_section_divider_holo_custom</item>
+        <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:textColor">@color/people_app_theme_color</item>
+        <item name="android:gravity">center_vertical</item>
+        <item name="android:paddingLeft">8dip</item>
+        <item name="android:ellipsize">end</item>
+        <item name="android:singleLine">true</item>
+        <item name="android:textAllCaps">true</item>
+    </style>
 </resources>
diff --git a/src/com/android/contacts/activities/DialtactsActivity.java b/src/com/android/contacts/activities/DialtactsActivity.java
index 15724c1..917d8e0 100644
--- a/src/com/android/contacts/activities/DialtactsActivity.java
+++ b/src/com/android/contacts/activities/DialtactsActivity.java
@@ -20,14 +20,13 @@
 import com.android.contacts.calllog.CallLogFragment;
 import com.android.contacts.dialpad.DialpadFragment;
 import com.android.contacts.interactions.PhoneNumberInteraction;
-import com.android.contacts.list.AccountFilterActivity;
-import com.android.contacts.list.ContactListFilter;
 import com.android.contacts.list.ContactListFilterController;
 import com.android.contacts.list.ContactListFilterController.ContactListFilterListener;
 import com.android.contacts.list.ContactListItemView;
 import com.android.contacts.list.OnPhoneNumberPickerActionListener;
 import com.android.contacts.list.PhoneFavoriteFragment;
 import com.android.contacts.list.PhoneNumberPickerFragment;
+import com.android.contacts.util.AccountFilterUtil;
 import com.android.internal.telephony.ITelephony;
 
 import android.app.ActionBar;
@@ -109,6 +108,8 @@
             "DialtactsActivity_last_manually_selected_tab";
     private static final int PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT = TAB_INDEX_DIALER;
 
+    private static final int SUBACTIVITY_ACCOUNT_FILTER = 1;
+
     /**
      * Listener interface for Fragments accommodated in {@link ViewPager} enabling them to know
      * when it becomes visible or invisible inside the ViewPager.
@@ -301,10 +302,8 @@
             new OnMenuItemClickListener() {
         @Override
         public boolean onMenuItemClick(MenuItem item) {
-            final Intent intent =
-                    new Intent(DialtactsActivity.this, AccountFilterActivity.class);
-            ContactListFilter filter = mContactListFilterController.getFilter();
-            startActivityForResult(intent, AccountFilterActivity.DEFAULT_REQUEST_CODE);
+            AccountFilterUtil.startAccountFilterActivityForResult(
+                    DialtactsActivity.this, SUBACTIVITY_ACCOUNT_FILTER);
             return true;
         }
     };
@@ -925,17 +924,9 @@
             return;
         }
         switch (requestCode) {
-            case AccountFilterActivity.DEFAULT_REQUEST_CODE: {
-                ContactListFilter filter = (ContactListFilter) data.getParcelableExtra(
-                        AccountFilterActivity.KEY_EXTRA_CONTACT_LIST_FILTER);
-                if (filter == null) {
-                    return;
-                }
-                if (filter.filterType == ContactListFilter.FILTER_TYPE_CUSTOM) {
-                    mContactListFilterController.selectCustomFilter();
-                } else {
-                    mContactListFilterController.setContactListFilter(filter, true);
-                }
+            case SUBACTIVITY_ACCOUNT_FILTER: {
+                AccountFilterUtil.handleAccountFilterResult(
+                        mContactListFilterController, resultCode, data);
             }
             break;
         }
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index 6f4089c..772fa54 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -33,7 +33,6 @@
 import com.android.contacts.interactions.ContactDeletionInteraction;
 import com.android.contacts.interactions.ImportExportDialogFragment;
 import com.android.contacts.interactions.PhoneNumberInteraction;
-import com.android.contacts.list.AccountFilterActivity;
 import com.android.contacts.list.ContactBrowseListFragment;
 import com.android.contacts.list.ContactEntryListFragment;
 import com.android.contacts.list.ContactListFilter;
@@ -53,6 +52,7 @@
 import com.android.contacts.model.AccountWithDataSet;
 import com.android.contacts.preference.ContactsPreferenceActivity;
 import com.android.contacts.preference.DisplayOptionsPreferenceFragment;
+import com.android.contacts.util.AccountFilterUtil;
 import com.android.contacts.util.AccountPromptUtils;
 import com.android.contacts.util.AccountSelectionUtil;
 import com.android.contacts.util.AccountsListAdapter;
@@ -61,7 +61,6 @@
 import com.android.contacts.util.DialogManager;
 import com.android.contacts.util.PhoneCapabilityTester;
 
-import android.app.Activity;
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
@@ -110,8 +109,9 @@
 
     private static final int SUBACTIVITY_NEW_GROUP = 2;
     private static final int SUBACTIVITY_EDIT_GROUP = 3;
+    private static final int SUBACTIVITY_ACCOUNT_FILTER = 4;
 
-    private DialogManager mDialogManager = new DialogManager(this);
+    private final DialogManager mDialogManager = new DialogManager(this);
 
     private ContactsIntentResolver mIntentResolver;
     private ContactsRequest mRequest;
@@ -1355,8 +1355,8 @@
                 return true;
             }
             case R.id.menu_contacts_filter: {
-                final Intent intent = new Intent(this, AccountFilterActivity.class);
-                startActivityForResult(intent, AccountFilterActivity.DEFAULT_REQUEST_CODE);
+                AccountFilterUtil.startAccountFilterActivityForResult(this,
+                        SUBACTIVITY_ACCOUNT_FILTER);
                 return true;
             }
             case R.id.menu_search: {
@@ -1434,19 +1434,9 @@
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         switch (requestCode) {
-            case AccountFilterActivity.DEFAULT_REQUEST_CODE: {
-                if (resultCode == Activity.RESULT_OK) {
-                    ContactListFilter filter = (ContactListFilter) data.getParcelableExtra(
-                            AccountFilterActivity.KEY_EXTRA_CONTACT_LIST_FILTER);
-                    if (filter == null) {
-                        return;
-                    }
-                    if (filter.filterType == ContactListFilter.FILTER_TYPE_CUSTOM) {
-                        mContactListFilterController.selectCustomFilter();
-                    } else {
-                        mContactListFilterController.setContactListFilter(filter, true);
-                    }
-                }
+            case SUBACTIVITY_ACCOUNT_FILTER: {
+                AccountFilterUtil.handleAccountFilterResult(
+                        mContactListFilterController, resultCode, data);
                 break;
             }
 
diff --git a/src/com/android/contacts/list/AccountFilterActivity.java b/src/com/android/contacts/list/AccountFilterActivity.java
index aa1fe27..0b4c6e0 100644
--- a/src/com/android/contacts/list/AccountFilterActivity.java
+++ b/src/com/android/contacts/list/AccountFilterActivity.java
@@ -55,15 +55,6 @@
 
     private static final int SUBACTIVITY_CUSTOMIZE_FILTER = 0;
 
-    /**
-     * Request code for this Activity, which will be used with
-     * {@link Activity#startActivityForResult(Intent, int)}.
-     *
-     * This is useful when we want to share one request code among multiple Activities and
-     * Fragments.
-     */
-    public static final int DEFAULT_REQUEST_CODE = 10001;
-
     public static final String KEY_EXTRA_CONTACT_LIST_FILTER = "contactListFilter";
 
     private static final int FILTER_LOADER_ID = 0;
diff --git a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
index a6700b5..0cc211a 100644
--- a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
@@ -17,13 +17,14 @@
 
 import com.android.contacts.R;
 import com.android.contacts.editor.ContactEditorFragment;
+import com.android.contacts.util.AccountFilterUtil;
 
-import android.app.Activity;
 import android.content.CursorLoader;
 import android.content.Intent;
 import android.database.Cursor;
 import android.provider.ContactsContract.Contacts;
 import android.text.TextUtils;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -40,11 +41,13 @@
  * picking a contact with one of the PICK intents).
  */
 public class DefaultContactBrowseListFragment extends ContactBrowseListFragment {
+    private static final String TAG = DefaultContactBrowseListFragment.class.getSimpleName();
+
+    private static final int REQUEST_CODE_ACCOUNT_FILTER = 1;
 
     private TextView mCounterHeaderView;
     private View mSearchHeaderView;
-    private TextView mAccountFilterHeaderView;
-    private View mAccountFilterHeaderContainer;
+    private View mAccountFilterHeader;
     private FrameLayout mProfileHeaderContainer;
     private View mProfileHeader;
     private Button mProfileMessage;
@@ -56,12 +59,8 @@
     private class FilterHeaderClickListener implements OnClickListener {
         @Override
         public void onClick(View view) {
-            final Activity activity = getActivity();
-            if (activity != null) {
-                final Intent intent = new Intent(activity, AccountFilterActivity.class);
-                activity.startActivityForResult(
-                        intent, AccountFilterActivity.DEFAULT_REQUEST_CODE);
-            }
+            AccountFilterUtil.startAccountFilterActivityForResult(
+                        DefaultContactBrowseListFragment.this, REQUEST_CODE_ACCOUNT_FILTER);
         }
     }
     private OnClickListener mFilterHeaderClickListener = new FilterHeaderClickListener();
@@ -92,17 +91,15 @@
 
     @Override
     protected View inflateView(LayoutInflater inflater, ViewGroup container) {
-        return inflater.inflate(R.layout.contacts_list_content, null);
+        return inflater.inflate(R.layout.contact_list_content, null);
     }
 
     @Override
     protected void onCreateView(LayoutInflater inflater, ViewGroup container) {
         super.onCreateView(inflater, container);
 
-        mAccountFilterHeaderView = (TextView) getView().findViewById(R.id.account_filter_header);
-        mAccountFilterHeaderContainer =
-                getView().findViewById(R.id.account_filter_header_container);
-        mAccountFilterHeaderContainer.setOnClickListener(mFilterHeaderClickListener);
+        mAccountFilterHeader = getView().findViewById(R.id.account_filter_header_container);
+        mAccountFilterHeader.setOnClickListener(mFilterHeaderClickListener);
         mCounterHeaderView = (TextView) getView().findViewById(R.id.contacts_count);
 
         // Create an empty user profile header and hide it for now (it will be visible if the
@@ -144,29 +141,17 @@
     }
 
     private void updateFilterHeaderView() {
-        ContactListFilter filter = getFilter();
-        if (mAccountFilterHeaderView == null) {
+        if (mAccountFilterHeader == null) {
             return; // Before onCreateView -- just ignore it.
         }
+        final ContactListFilter filter = getFilter();
         if (filter != null && !isSearchMode()) {
-            if (filter.filterType == ContactListFilter.FILTER_TYPE_SINGLE_CONTACT) {
-                mAccountFilterHeaderContainer.setVisibility(View.VISIBLE);
-                mAccountFilterHeaderView.setText(getContext().getString(
-                        R.string.listSingleContact));
-                return;
-            } else if (filter.filterType == ContactListFilter.FILTER_TYPE_CUSTOM) {
-                mAccountFilterHeaderContainer.setVisibility(View.VISIBLE);
-                mAccountFilterHeaderView.setText(getContext().getString(
-                        R.string.listCustomView));
-                return;
-            } else if (filter.filterType != ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS) {
-                mAccountFilterHeaderContainer.setVisibility(View.VISIBLE);
-                mAccountFilterHeaderView.setText(getContext().getString(
-                        R.string.listAllContactsInAccount, filter.accountName));
-                return;
-            }
+            final boolean shouldShowHeader = AccountFilterUtil.updateAccountFilterTitleForPeople(
+                    mAccountFilterHeader, filter, false, false);
+            mAccountFilterHeader.setVisibility(shouldShowHeader ? View.VISIBLE : View.GONE);
+        } else {
+            mAccountFilterHeader.setVisibility(View.GONE);
         }
-        mAccountFilterHeaderContainer.setVisibility(View.GONE);
     }
 
     @Override
@@ -244,6 +229,18 @@
         showEmptyUserProfile(!mUserProfileExists && !isSearchMode());
     }
 
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == REQUEST_CODE_ACCOUNT_FILTER) {
+            if (getActivity() != null) {
+                AccountFilterUtil.handleAccountFilterResult(
+                        ContactListFilterController.getInstance(getActivity()), resultCode, data);
+            } else {
+                Log.e(TAG, "getActivity() returns null during Fragment#onActivityResult()");
+            }
+        }
+    }
+
     private void showEmptyUserProfile(boolean show) {
         // Changing visibility of just the mProfileHeader doesn't do anything unless
         // you change visibility of its children, hence the call to mCounterHeaderView
diff --git a/src/com/android/contacts/list/EmailAddressPickerFragment.java b/src/com/android/contacts/list/EmailAddressPickerFragment.java
index 168e135..14b6c23 100644
--- a/src/com/android/contacts/list/EmailAddressPickerFragment.java
+++ b/src/com/android/contacts/list/EmailAddressPickerFragment.java
@@ -55,7 +55,7 @@
 
     @Override
     protected View inflateView(LayoutInflater inflater, ViewGroup container) {
-        return inflater.inflate(R.layout.contacts_list_content, null);
+        return inflater.inflate(R.layout.contact_list_content, null);
     }
 
     private void pickEmailAddress(Uri uri) {
diff --git a/src/com/android/contacts/list/PhoneFavoriteFragment.java b/src/com/android/contacts/list/PhoneFavoriteFragment.java
index 437aca3..9ee2d3c 100644
--- a/src/com/android/contacts/list/PhoneFavoriteFragment.java
+++ b/src/com/android/contacts/list/PhoneFavoriteFragment.java
@@ -19,6 +19,7 @@
 import com.android.contacts.ContactTileLoaderFactory;
 import com.android.contacts.R;
 import com.android.contacts.preference.ContactsPreferences;
+import com.android.contacts.util.AccountFilterUtil;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -39,6 +40,7 @@
 import android.widget.AbsListView;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
+import android.widget.FrameLayout;
 import android.widget.ListView;
 import android.widget.TextView;
 
@@ -62,6 +64,8 @@
 
     private static final String KEY_FILTER = "filter";
 
+    private static final int REQUEST_CODE_ACCOUNT_FILTER = 1;
+
     public interface Listener {
         public void onContactSelected(Uri contactUri);
     }
@@ -93,7 +97,7 @@
 
             // Show the filter header with "loading" state.
             updateFilterHeaderView();
-            mAccountFilterHeaderContainer.setVisibility(View.VISIBLE);
+            mAccountFilterHeader.setVisibility(View.VISIBLE);
         }
 
         @Override
@@ -137,12 +141,8 @@
     private class FilterHeaderClickListener implements OnClickListener {
         @Override
         public void onClick(View view) {
-            final Activity activity = getActivity();
-            if (activity != null) {
-                final Intent intent = new Intent(activity, AccountFilterActivity.class);
-                activity.startActivityForResult(
-                        intent, AccountFilterActivity.DEFAULT_REQUEST_CODE);
-            }
+            AccountFilterUtil.startAccountFilterActivityForResult(
+                    PhoneFavoriteFragment.this, REQUEST_CODE_ACCOUNT_FILTER);
         }
     }
 
@@ -197,8 +197,11 @@
 
     private TextView mEmptyView;
     private ListView mListView;
-    private View mAccountFilterHeaderContainer;
-    private TextView mAccountFilterHeaderView;
+    /**
+     * Layout containing {@link #mAccountFilterHeader}. Used to limit area being "pressed".
+     */
+    private FrameLayout mAccountFilterHeaderContainer;
+    private View mAccountFilterHeader;
 
     private final ContactTileAdapter.Listener mContactTileAdapterListener =
             new ContactTileAdapterListener();
@@ -300,11 +303,10 @@
         }
 
         // Create the account filter header but keep it hidden until "all" contacts are loaded.
-        mAccountFilterHeaderContainer = inflater.inflate(
-                R.layout.phone_favorite_account_filter_header, mListView, false);
-        mAccountFilterHeaderView =
-                (TextView) mAccountFilterHeaderContainer.findViewById(R.id.account_filter_header);
-        mAccountFilterHeaderContainer.setOnClickListener(mFilterHeaderClickListener);
+        mAccountFilterHeaderContainer = new FrameLayout(context, null);
+        mAccountFilterHeader = inflater.inflate(R.layout.account_filter_header, mListView, false);
+        mAccountFilterHeader.setOnClickListener(mFilterHeaderClickListener);
+        mAccountFilterHeaderContainer.addView(mAccountFilterHeader);
         mAccountFilterHeaderContainer.setVisibility(View.GONE);
 
         mAdapter = new PhoneFavoriteMergedAdapter(context,
@@ -356,6 +358,18 @@
         }
     }
 
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == REQUEST_CODE_ACCOUNT_FILTER) {
+            if (getActivity() != null) {
+                AccountFilterUtil.handleAccountFilterResult(
+                        ContactListFilterController.getInstance(getActivity()), resultCode, data);
+            } else {
+                Log.e(TAG, "getActivity() returns null during Fragment#onActivityResult()");
+            }
+        }
+    }
+
     private boolean loadContactsPreferences() {
         if (mContactsPrefs == null || mAllContactsAdapter == null) {
             return false;
@@ -401,27 +415,12 @@
     }
 
     private void updateFilterHeaderView() {
-        if (mAccountFilterHeaderContainer == null || mAllContactsAdapter == null) {
+        final ContactListFilter filter = getFilter();
+        if (mAccountFilterHeader == null || mAllContactsAdapter == null || filter == null) {
             return;
         }
-
-        final ContactListFilter filter = getFilter();
-        if (mAllContactsAdapter.isLoading()) {
-            mAccountFilterHeaderView.setText(R.string.contact_list_loading);
-        } else if (filter != null) {
-            if (filter.filterType == ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS) {
-                mAccountFilterHeaderView.setText(R.string.list_filter_phones);
-            } else if (filter.filterType == ContactListFilter.FILTER_TYPE_ACCOUNT) {
-                mAccountFilterHeaderView.setText(getString(
-                        R.string.listAllContactsInAccount, filter.accountName));
-            } else if (filter.filterType == ContactListFilter.FILTER_TYPE_CUSTOM) {
-                mAccountFilterHeaderView.setText(R.string.listCustomView);
-            } else {
-                Log.w(TAG, "Filter type \"" + filter.filterType + "\" isn't expected.");
-            }
-        } else {
-            Log.w(TAG, "Filter is null.");
-        }
+        AccountFilterUtil.updateAccountFilterTitleForPhone(
+                mAccountFilterHeader, filter, mAllContactsAdapter.isLoading(), true);
     }
 
     public ContactListFilter getFilter() {
diff --git a/src/com/android/contacts/list/PhoneFavoriteMergedAdapter.java b/src/com/android/contacts/list/PhoneFavoriteMergedAdapter.java
index 0df4b3d..205e156 100644
--- a/src/com/android/contacts/list/PhoneFavoriteMergedAdapter.java
+++ b/src/com/android/contacts/list/PhoneFavoriteMergedAdapter.java
@@ -184,7 +184,8 @@
         if (position < contactTileAdapterCount) {
             return mContactTileAdapter.isEnabled(position);
         } else if (position == contactTileAdapterCount) {
-            return mAccountFilterHeaderContainer.isEnabled();
+            // This will be handled by View's onClick event instead of ListView's onItemClick event.
+            return false;
         } else {
             final int localPosition = position - contactTileAdapterCount - 1;
             return mContactEntryListAdapter.isEnabled(localPosition);
diff --git a/src/com/android/contacts/list/PhoneNumberPickerFragment.java b/src/com/android/contacts/list/PhoneNumberPickerFragment.java
index 602b06a..052c32f 100644
--- a/src/com/android/contacts/list/PhoneNumberPickerFragment.java
+++ b/src/com/android/contacts/list/PhoneNumberPickerFragment.java
@@ -17,8 +17,8 @@
 
 import com.android.contacts.R;
 import com.android.contacts.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
+import com.android.contacts.util.AccountFilterUtil;
 
-import android.app.Activity;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
@@ -28,7 +28,6 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
-import android.widget.TextView;
 
 /**
  * Fragment containing a phone number list for picking.
@@ -37,15 +36,16 @@
         implements OnShortcutIntentCreatedListener {
     private static final String TAG = PhoneNumberPickerFragment.class.getSimpleName();
 
+    private static final int REQUEST_CODE_ACCOUNT_FILTER = 1;
+
     private OnPhoneNumberPickerActionListener mListener;
     private String mShortcutAction;
 
     private ContactListFilter mFilter;
 
-    private TextView mAccountFilterHeaderView;
-    private View mAccountFilterHeaderContainer;
+    private View mAccountFilterHeader;
     /**
-     * Lives as ListView's header and is shown when {@link #mAccountFilterHeaderContainer} is set
+     * Lives as ListView's header and is shown when {@link #mAccountFilterHeader} is set
      * to View.GONE.
      */
     private View mPaddingView;
@@ -58,17 +58,11 @@
     private ContactListItemView.PhotoPosition mPhotoPosition =
             ContactListItemView.DEFAULT_PHOTO_POSITION;
 
-    // A complete copy from DefaultContactBrowserListFragment
-    // TODO: should be able to share logic around filter header.
     private class FilterHeaderClickListener implements OnClickListener {
         @Override
         public void onClick(View view) {
-            final Activity activity = getActivity();
-            if (activity != null) {
-                final Intent intent = new Intent(activity, AccountFilterActivity.class);
-                activity.startActivityForResult(
-                        intent, AccountFilterActivity.DEFAULT_REQUEST_CODE);
-            }
+            AccountFilterUtil.startAccountFilterActivityForResult(
+                    PhoneNumberPickerFragment.this, REQUEST_CODE_ACCOUNT_FILTER);
         }
     }
     private OnClickListener mFilterHeaderClickListener = new FilterHeaderClickListener();
@@ -96,10 +90,8 @@
         mPaddingView = paddingView.findViewById(R.id.contact_detail_list_padding);
         getListView().addHeaderView(paddingView);
 
-        mAccountFilterHeaderView = (TextView) getView().findViewById(R.id.account_filter_header);
-        mAccountFilterHeaderContainer =
-                getView().findViewById(R.id.account_filter_header_container);
-        mAccountFilterHeaderContainer.setOnClickListener(mFilterHeaderClickListener);
+        mAccountFilterHeader = getView().findViewById(R.id.account_filter_header_container);
+        mAccountFilterHeader.setOnClickListener(mFilterHeaderClickListener);
         updateFilterHeaderView();
     }
 
@@ -110,31 +102,18 @@
     }
 
     private void updateFilterHeaderView() {
-        if (mAccountFilterHeaderView != null) {
-            ContactListFilter filter = getFilter();
-            if (filter != null && !isSearchMode()) {
-                if (filter.filterType == ContactListFilter.FILTER_TYPE_SINGLE_CONTACT) {
-                    mAccountFilterHeaderContainer.setVisibility(View.VISIBLE);
-                    mAccountFilterHeaderView.setText(getContext().getString(
-                            R.string.listSingleContact));
-                    mPaddingView.setVisibility(View.GONE);
-                    return;
-                } else if (filter.filterType == ContactListFilter.FILTER_TYPE_CUSTOM) {
-                    mAccountFilterHeaderContainer.setVisibility(View.VISIBLE);
-                    mAccountFilterHeaderView.setText(getContext().getString(
-                            R.string.listCustomView));
-                    mPaddingView.setVisibility(View.GONE);
-                    return;
-                } else if (filter.filterType != ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS) {
-                    mAccountFilterHeaderContainer.setVisibility(View.VISIBLE);
-                    mAccountFilterHeaderView.setText(getContext().getString(
-                            R.string.listAllContactsInAccount, filter.accountName));
-                    mPaddingView.setVisibility(View.GONE);
-                    return;
-                }
-            }
-            mAccountFilterHeaderContainer.setVisibility(View.GONE);
+        final ContactListFilter filter = getFilter();
+        if (mAccountFilterHeader == null || filter == null) {
+            return;
+        }
+        final boolean shouldShowHeader = AccountFilterUtil.updateAccountFilterTitleForPhone(
+                mAccountFilterHeader, filter, false, false);
+        if (shouldShowHeader) {
+            mPaddingView.setVisibility(View.GONE);
+            mAccountFilterHeader.setVisibility(View.VISIBLE);
+        } else {
             mPaddingView.setVisibility(View.VISIBLE);
+            mAccountFilterHeader.setVisibility(View.GONE);
         }
     }
 
@@ -233,7 +212,7 @@
 
     @Override
     protected View inflateView(LayoutInflater inflater, ViewGroup container) {
-        return inflater.inflate(R.layout.contacts_list_content, null);
+        return inflater.inflate(R.layout.contact_list_content, null);
     }
 
     public void pickPhoneNumber(Uri uri) {
@@ -257,6 +236,18 @@
         mListener.onPickPhoneNumberAction(data.getData());
     }
 
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == REQUEST_CODE_ACCOUNT_FILTER) {
+            if (getActivity() != null) {
+                AccountFilterUtil.handleAccountFilterResult(
+                        ContactListFilterController.getInstance(getActivity()), resultCode, data);
+            } else {
+                Log.e(TAG, "getActivity() returns null during Fragment#onActivityResult()");
+            }
+        }
+    }
+
     public ContactListFilter getFilter() {
         return mFilter;
     }
diff --git a/src/com/android/contacts/list/PostalAddressPickerFragment.java b/src/com/android/contacts/list/PostalAddressPickerFragment.java
index 5f7ca56..85fc155 100644
--- a/src/com/android/contacts/list/PostalAddressPickerFragment.java
+++ b/src/com/android/contacts/list/PostalAddressPickerFragment.java
@@ -70,7 +70,7 @@
 
     @Override
     protected View inflateView(LayoutInflater inflater, ViewGroup container) {
-        return inflater.inflate(R.layout.contacts_list_content, null);
+        return inflater.inflate(R.layout.contact_list_content, null);
     }
 
     private void pickPostalAddress(Uri uri) {
diff --git a/src/com/android/contacts/util/AccountFilterUtil.java b/src/com/android/contacts/util/AccountFilterUtil.java
new file mode 100644
index 0000000..955c195
--- /dev/null
+++ b/src/com/android/contacts/util/AccountFilterUtil.java
@@ -0,0 +1,165 @@
+/*
+ * 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.util;
+
+import com.android.contacts.R;
+import com.android.contacts.list.AccountFilterActivity;
+import com.android.contacts.list.ContactListFilter;
+import com.android.contacts.list.ContactListFilterController;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+import android.view.View;
+import android.widget.TextView;
+
+/**
+ * Utility class for account filter manipulation.
+ */
+public class AccountFilterUtil {
+    private static final String TAG = AccountFilterUtil.class.getSimpleName();
+
+    /**
+     * Find TextView with the id "account_filter_header" and set correct text for the account
+     * filter header.
+     *
+     * @param filterContainer View containing TextView with id "account_filter_header"
+     * @return true when header text is set in the call. You may use this for conditionally
+     * showing or hiding this entire view.
+     */
+    public static boolean updateAccountFilterTitleForPeople(View filterContainer,
+            ContactListFilter filter, boolean isLoading, boolean showTitleForAllAccounts) {
+        return updateAccountFilterTitle(
+                filterContainer, filter, isLoading, showTitleForAllAccounts, false);
+    }
+
+    /**
+     * Similar to {@link #updateAccountFilterTitleForPeople(View, ContactListFilter, boolean,
+     * boolean)}, but for Phone UI.
+     */
+    public static boolean updateAccountFilterTitleForPhone(View filterContainer,
+            ContactListFilter filter, boolean isLoading, boolean showTitleForAllAccounts) {
+        return updateAccountFilterTitle(
+                filterContainer, filter, isLoading, showTitleForAllAccounts, true);
+    }
+
+    private static boolean updateAccountFilterTitle(View filterContainer,
+            ContactListFilter filter, boolean isLoading, boolean showTitleForAllAccounts,
+            boolean forPhone) {
+        final Context context = filterContainer.getContext();
+        final TextView headerTextView = (TextView)
+                filterContainer.findViewById(R.id.account_filter_header);
+
+        boolean textWasSet = false;
+        if (isLoading) {
+            headerTextView.setText(R.string.contact_list_loading);
+        } else if (filter != null) {
+            if (forPhone) {
+                if (filter.filterType == ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS) {
+                    if (showTitleForAllAccounts) {
+                        headerTextView.setText(R.string.list_filter_phones);
+                        textWasSet = true;
+                    }
+                } else if (filter.filterType == ContactListFilter.FILTER_TYPE_ACCOUNT) {
+                    headerTextView.setText(context.getString(
+                            R.string.listAllContactsInAccount, filter.accountName));
+                    textWasSet = true;
+                } else if (filter.filterType == ContactListFilter.FILTER_TYPE_CUSTOM) {
+                    headerTextView.setText(R.string.listCustomView);
+                    textWasSet = true;
+                } else {
+                    Log.w(TAG, "Filter type \"" + filter.filterType + "\" isn't expected.");
+                }
+            } else {
+                if (filter.filterType == ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS) {
+                    if (showTitleForAllAccounts) {
+                        headerTextView.setText(R.string.list_filter_all_accounts);
+                        textWasSet = true;
+                    }
+                } else if (filter.filterType == ContactListFilter.FILTER_TYPE_ACCOUNT) {
+                    headerTextView.setText(context.getString(
+                            R.string.listAllContactsInAccount, filter.accountName));
+                    textWasSet = true;
+                } else if (filter.filterType == ContactListFilter.FILTER_TYPE_CUSTOM) {
+                    headerTextView.setText(R.string.listCustomView);
+                    textWasSet = true;
+                } else if (filter.filterType == ContactListFilter.FILTER_TYPE_SINGLE_CONTACT) {
+                    headerTextView.setText(R.string.listSingleContact);
+                    textWasSet = true;
+                } else {
+                    Log.w(TAG, "Filter type \"" + filter.filterType + "\" isn't expected.");
+                }
+            }
+        } else {
+            Log.w(TAG, "Filter is null.");
+        }
+        return textWasSet;
+    }
+
+    /**
+     * Launches account filter setting Activity using
+     * {@link Activity#startActivityForResult(Intent, int)}.
+     *
+     * @param activity
+     * @param requestCode requestCode for {@link Activity#startActivityForResult(Intent, int)}
+     */
+    public static void startAccountFilterActivityForResult(
+            Activity activity, int requestCode) {
+        final Intent intent = new Intent(activity, AccountFilterActivity.class);
+        activity.startActivityForResult(intent, requestCode);
+    }
+
+    /**
+     * Very similar to {@link #startAccountFilterActivityForResult(Activity, int)} but uses
+     * Fragment instead.
+     */
+    public static void startAccountFilterActivityForResult(
+            Fragment fragment, int requestCode) {
+        final Activity activity = fragment.getActivity();
+        if (activity != null) {
+            final Intent intent = new Intent(activity, AccountFilterActivity.class);
+            fragment.startActivityForResult(intent, requestCode);
+        } else {
+            Log.w(TAG, "getActivity() returned null. Ignored");
+        }
+    }
+
+    /**
+     * Useful method to handle onActivityResult() for
+     * {@link #startAccountFilterActivityForResult(Activity, int)} or
+     * {@link #startAccountFilterActivityForResult(Fragment, int)}.
+     *
+     * This will update filter via a given ContactListFilterController.
+     */
+    public static void handleAccountFilterResult(
+            ContactListFilterController filterController, int resultCode, Intent data) {
+        if (resultCode == Activity.RESULT_OK) {
+            final ContactListFilter filter = (ContactListFilter)
+                    data.getParcelableExtra(AccountFilterActivity.KEY_EXTRA_CONTACT_LIST_FILTER);
+            if (filter == null) {
+                return;
+            }
+            if (filter.filterType == ContactListFilter.FILTER_TYPE_CUSTOM) {
+                filterController.selectCustomFilter();
+            } else {
+                filterController.setContactListFilter(filter, true);
+            }
+        }
+    }
+}
\ No newline at end of file