Merge "Hide FAB if the account is read-only"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 27c9f96..6a0338a 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -508,5 +508,11 @@
         </provider>
 
         <meta-data android:name="android.nfc.disable_beam_default" android:value="true" />
+
+        <receiver android:name="com.android.contacts.editor.AccountsChangedBroadcastReceiver">
+            <intent-filter>
+                <action android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED"/>
+            </intent-filter>
+        </receiver>
     </application>
 </manifest>
diff --git a/res/layout/group_member_suggestion.xml b/res/layout/group_member_suggestion.xml
deleted file mode 100644
index 4fe8d20..0000000
--- a/res/layout/group_member_suggestion.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="48dip"
-    android:orientation="horizontal"
-    android:gravity="center_vertical"
-    android:background="?android:attr/selectableItemBackground">
-
-    <LinearLayout
-        android:layout_width="0dip"
-        android:layout_height="match_parent"
-        android:layout_weight="1"
-        android:gravity="center_vertical"
-        android:orientation="vertical">
-
-        <TextView
-            android:id="@+id/text1"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:paddingLeft="8dip"
-            android:paddingStart="8dip"
-            android:singleLine="true"
-            android:ellipsize="end"/>
-
-        <TextView android:id="@+id/text2"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorSecondary"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:paddingLeft="8dip"
-            android:paddingStart="8dip"
-            android:singleLine="true"
-            android:ellipsize="end" />
-
-    </LinearLayout>
-
-    <ImageView
-        android:id="@+id/icon"
-        android:layout_width="48dip"
-        android:layout_height="48dip"
-        android:cropToPadding="true"
-        android:scaleType="centerCrop" />
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/menu/view_group.xml b/res/menu/view_group.xml
index 2fc36be..cf945fd 100644
--- a/res/menu/view_group.xml
+++ b/res/menu/view_group.xml
@@ -24,11 +24,6 @@
         contacts:showAsAction="ifRoom" />
 
     <item
-        android:id="@+id/menu_search"
-        android:icon="@drawable/ic_ab_search"
-        android:title="@string/menu_search" />
-
-    <item
         android:id="@+id/menu_rename_group"
         android:title="@string/menu_renameGroup"/>
 
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 880460b..995ed06 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -134,8 +134,8 @@
         <item name="colorPrimary">@color/primary_color</item>
         <item name="android:colorAccent">@color/primary_color</item>
         <item name="colorAccent">@color/primary_color</item>
-        <item name="android:alertDialogTheme">@style/ContactsAlertDialogTheme</item>
-        <item name="alertDialogTheme">@style/ContactsAlertDialogTheme</item>
+        <item name="android:alertDialogTheme">@style/ContactsAlertDialogThemeAppCompat</item>
+        <item name="alertDialogTheme">@style/ContactsAlertDialogThemeAppCompat</item>
         <item name="list_item_height">?android:attr/listPreferredItemHeight</item>
         <item name="activated_background">@drawable/list_item_activated_background</item>
         <item name="section_header_background">@drawable/list_title_holo</item>
@@ -376,7 +376,13 @@
         <item name="android:fontFamily">sans-serif</item>
     </style>
 
-    <style name="ContactsAlertDialogTheme" parent="Theme.AppCompat.Light.Dialog.MinWidth">
+    <!-- Inherit from Theme.Material.Light.Dialog instead of Theme.Material.Light.Dialog.Alert
+        since the Alert dialog is private. They are identical anyway. -->
+    <style name="ContactsAlertDialogTheme" parent="@android:style/Theme.Material.Light.Dialog">
+        <item name="android:colorAccent">@color/primary_color</item>
+    </style>
+
+    <style name="ContactsAlertDialogThemeAppCompat" parent="Theme.AppCompat.Light.Dialog.MinWidth">
         <item name="android:colorAccent">@color/primary_color</item>
         <item name="colorAccent">@color/primary_color</item>
     </style>
diff --git a/src/com/android/contacts/GroupMemberLoader.java b/src/com/android/contacts/GroupMemberLoader.java
index 9f55848..8bc7d04 100644
--- a/src/com/android/contacts/GroupMemberLoader.java
+++ b/src/com/android/contacts/GroupMemberLoader.java
@@ -52,34 +52,8 @@
         public static final int CONTACT_PHOTO_ID             = 5;
     }
 
-    public static class GroupDetailQuery {
-        private static final String[] PROJECTION = new String[] {
-            Data.CONTACT_ID,                        // 0
-            Data.PHOTO_URI,                         // 1
-            Data.LOOKUP_KEY,                        // 2
-            Data.DISPLAY_NAME_PRIMARY,              // 3
-            Data.CONTACT_PRESENCE,                  // 4
-            Data.CONTACT_STATUS,                    // 5
-        };
-
-        public static final int CONTACT_ID                   = 0;
-        public static final int CONTACT_PHOTO_URI            = 1;
-        public static final int CONTACT_LOOKUP_KEY           = 2;
-        public static final int CONTACT_DISPLAY_NAME_PRIMARY = 3;
-        public static final int CONTACT_PRESENCE_STATUS      = 4;
-        public static final int CONTACT_STATUS               = 5;
-    }
-
     private final long mGroupId;
 
-    /**
-     * @return GroupMemberLoader object which can be used in group editor.
-     */
-    public static GroupMemberLoader constructLoaderForGroupEditorQuery(
-            Context context, long groupId) {
-        return new GroupMemberLoader(context, groupId, GroupEditorQuery.PROJECTION);
-    }
-
     private GroupMemberLoader(Context context, long groupId, String[] projection) {
         super(context);
         mGroupId = groupId;
diff --git a/src/com/android/contacts/activities/ContactEditorBaseActivity.java b/src/com/android/contacts/activities/ContactEditorBaseActivity.java
index ffbeb49..97095f0 100644
--- a/src/com/android/contacts/activities/ContactEditorBaseActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorBaseActivity.java
@@ -16,6 +16,18 @@
 
 package com.android.contacts.activities;
 
+import android.app.ActionBar;
+import android.app.Dialog;
+import android.content.ContentValues;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.RawContacts;
+import android.util.Log;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+
 import com.android.contacts.ContactSaveService;
 import com.android.contacts.ContactsActivity;
 import com.android.contacts.R;
@@ -29,18 +41,6 @@
 import com.android.contacts.interactions.ContactDeletionInteraction;
 import com.android.contacts.util.DialogManager;
 
-import android.app.ActionBar;
-import android.app.Dialog;
-import android.content.ContentValues;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.RawContacts;
-import android.util.Log;
-import android.view.View;
-import android.view.inputmethod.InputMethodManager;
-
 import java.util.ArrayList;
 
 /**
@@ -68,6 +68,8 @@
     public static final String ACTION_SAVE_COMPLETED = "saveCompleted";
 
     public static final int RESULT_CODE_SPLIT = 2;
+    // 3 used for ContactDeletionInteraction.RESULT_CODE_DELETED
+    public static final int RESULT_CODE_EDITED = 4;
 
     protected int mActionBarTitleResId;
 
diff --git a/src/com/android/contacts/activities/ContactSelectionActivity.java b/src/com/android/contacts/activities/ContactSelectionActivity.java
index 80a4acb..6e2746d 100644
--- a/src/com/android/contacts/activities/ContactSelectionActivity.java
+++ b/src/com/android/contacts/activities/ContactSelectionActivity.java
@@ -139,10 +139,9 @@
                 .inflate(R.layout.custom_action_bar, null);
         mSearchView = (SearchView) mSearchViewContainer.findViewById(R.id.search_view);
 
-        // Postal address  group member,and legacy pickers don't support search, so just show
+        // Postal address pickers (and legacy pickers) don't support search, so just show
         // "HomeAsUp" button and title.
         if (mRequest.getActionCode() == ContactsRequest.ACTION_PICK_POSTAL ||
-                mRequest.getActionCode() == ContactsRequest.ACTION_PICK_GROUP_MEMBERS ||
                 mRequest.isLegacyCompatibilityMode()) {
             mSearchView.setVisibility(View.GONE);
             if (actionBar != null) {
@@ -359,9 +358,9 @@
             case ContactsRequest.ACTION_PICK_GROUP_MEMBERS: {
                 final AccountWithDataSet account = getIntent().getParcelableExtra(
                         UiIntentActions.GROUP_ACCOUNT_WITH_DATA_SET);
-                final ArrayList<String> rawContactIds = getIntent().getStringArrayListExtra(
-                        UiIntentActions.GROUP_RAW_CONTACT_IDS);
-                mListFragment = GroupMemberPickerFragment.newInstance(account, rawContactIds);
+                final ArrayList<String> contactIds = getIntent().getStringArrayListExtra(
+                        UiIntentActions.GROUP_CONTACT_IDS);
+                mListFragment = GroupMemberPickerFragment.newInstance(account, contactIds);
                 break;
             }
 
@@ -483,8 +482,10 @@
     private final class GroupMemberPickerListener implements GroupMemberPickerFragment.Listener {
 
         @Override
-        public void onGroupMemberClicked(Uri uri) {
-            returnPickerResult(uri);
+        public void onGroupMemberClicked(long contactId) {
+            final Intent intent = new Intent();
+            intent.putExtra(UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, contactId);
+            returnPickerResult(intent);
         }
     }
 
diff --git a/src/com/android/contacts/activities/GroupMembersActivity.java b/src/com/android/contacts/activities/GroupMembersActivity.java
index f41972e..f1242d6 100644
--- a/src/com/android/contacts/activities/GroupMembersActivity.java
+++ b/src/com/android/contacts/activities/GroupMembersActivity.java
@@ -17,29 +17,23 @@
 
 import android.accounts.Account;
 import android.app.FragmentManager;
-import android.app.LoaderManager.LoaderCallbacks;
-import android.content.CursorLoader;
+import android.content.Context;
 import android.content.Intent;
-import android.content.Loader;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.Intents;
+import android.provider.ContactsContract.RawContacts;
 import android.support.v7.widget.Toolbar;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.AutoCompleteTextView;
 import android.widget.Toast;
 
 import com.android.contacts.AppCompatContactsActivity;
 import com.android.contacts.ContactSaveService;
-import com.android.contacts.GroupMemberLoader;
-import com.android.contacts.GroupMemberLoader.GroupEditorQuery;
 import com.android.contacts.R;
 import com.android.contacts.common.editor.SelectAccountDialogFragment;
 import com.android.contacts.common.logging.ListEvent;
@@ -53,9 +47,6 @@
 import com.android.contacts.group.GroupMembersListFragment;
 import com.android.contacts.group.GroupMetadata;
 import com.android.contacts.group.GroupNameEditDialogFragment;
-import com.android.contacts.group.Member;
-import com.android.contacts.group.SuggestedMemberListAdapter;
-import com.android.contacts.group.SuggestedMemberListAdapter.SuggestedMember;
 import com.android.contacts.interactions.GroupDeletionDialogFragment;
 import com.android.contacts.list.ContactsRequest;
 import com.android.contacts.list.MultiSelectContactsListFragment;
@@ -85,8 +76,6 @@
     private static final String TAG_SELECT_ACCOUNT_DIALOG = "selectAccountDialog";
     private static final String TAG_GROUP_NAME_EDIT_DIALOG = "groupNameEditDialog";
 
-    private static final int LOADER_GROUP_MEMBERS = 0;
-
     private static final String ACTION_DELETE_GROUP = "deleteGroup";
     private static final String ACTION_CREATE_GROUP = "createGroup";
     private static final String ACTION_UPDATE_GROUP = "updateGroup";
@@ -95,35 +84,74 @@
 
     private static final int RESULT_GROUP_ADD_MEMBER = 100;
 
-    /** Loader callbacks for existing group members for the autocomplete text view. */
-    private final LoaderCallbacks<Cursor> mGroupMemberCallbacks = new LoaderCallbacks<Cursor>() {
+    /**
+     * Starts an Intent to add the raw contacts for a given contact ID to a group.
+     * Only the raw contacts that belong to the specified account are added.
+     */
+    private static class AddGroupMembersAsyncTask extends AsyncTask<Void, Void, Intent> {
 
-        @Override
-        public CursorLoader onCreateLoader(int id, Bundle args) {
-            return GroupMemberLoader.constructLoaderForGroupEditorQuery(
-                    GroupMembersActivity.this, mGroupMetadata.groupId);
+        private final Context mContext;
+        private final long mContactId;
+        private final long mGroupId;
+        private final String mAccountName;
+        private final String mAccountType;
+
+        AddGroupMembersAsyncTask(Context context, long contactId, long groupId, String accountName,
+                String accountType) {
+            mContext = context;
+            mContactId = contactId;
+            mGroupId = groupId;
+            mAccountName = accountName;
+            mAccountType = accountType;
         }
 
         @Override
-        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
-            final List<Member> members = new ArrayList<>();
-            data.moveToPosition(-1);
-            while (data.moveToNext()) {
-                members.add(new Member(
-                        data.getLong(GroupEditorQuery.RAW_CONTACT_ID),
-                        data.getString(GroupEditorQuery.CONTACT_LOOKUP_KEY),
-                        data.getLong(GroupEditorQuery.CONTACT_ID),
-                        data.getString(GroupEditorQuery.CONTACT_DISPLAY_NAME_PRIMARY),
-                        data.getString(GroupEditorQuery.CONTACT_PHOTO_URI),
-                        data.getLong(GroupEditorQuery.CONTACT_PHOTO_ID)));
+        protected Intent doInBackground(Void... params) {
+            final long[] rawContactIdsToAdd = getRawContactIdsToAdd();
+            if (rawContactIdsToAdd.length == 0) {
+                return null;
             }
+            return ContactSaveService.createGroupUpdateIntent(
+                    mContext, mGroupId, /* newLabel */ null,
+                    rawContactIdsToAdd, /* rawContactIdsToRemove */ null,
+                    GroupMembersActivity.class, GroupMembersActivity.ACTION_ADD_TO_GROUP);
+        }
 
-            bindAutocompleteGroupMembers(members);
+        // TODO(wjang): prune raw contacts that are already in the group; ContactSaveService will
+        // log a warning if the raw contact is already a member and keep going but it is not ideal.
+        private long[] getRawContactIdsToAdd() {
+            final Uri rawContactUri = RawContacts.CONTENT_URI.buildUpon()
+                    .appendQueryParameter(RawContacts.ACCOUNT_NAME, mAccountName)
+                    .appendQueryParameter(RawContacts.ACCOUNT_TYPE, mAccountType)
+                    .build();
+            final String[] projection = new String[]{RawContacts._ID};
+            final String selection = RawContacts.CONTACT_ID + "=?";
+            final String[] selectionArgs = new String[1];
+            selectionArgs[0] = Long.toString(mContactId);
+            final Cursor cursor = mContext.getContentResolver().query(
+                    rawContactUri, projection, selection, selectionArgs, null, null);
+            final long[] rawContactIds = new long[cursor.getCount()];
+            try {
+                int i = 0;
+                while (cursor.moveToNext()) {
+                    rawContactIds[i] = cursor.getLong(0);
+                    i++;
+                }
+            } finally {
+                cursor.close();
+            }
+            return rawContactIds;
         }
 
         @Override
-        public void onLoaderReset(Loader<Cursor> loader) {}
-    };
+        protected void onPostExecute(Intent intent) {
+            if (intent == null) {
+                Toast.makeText(mContext, R.string.groupSavedErrorToast, Toast.LENGTH_SHORT).show();
+            } else {
+                mContext.startService(intent);
+            }
+        }
+    }
 
     private ActionBarAdapter mActionBarAdapter;
 
@@ -131,8 +159,6 @@
 
     private GroupMembersListFragment mMembersListFragment;
 
-    private SuggestedMemberListAdapter mAutoCompleteAdapter;
-
     private Uri mGroupUri;
     private boolean mIsInsertAction;
 
@@ -198,8 +224,6 @@
                 fragmentManager.beginTransaction()
                         .replace(R.id.fragment_container, mMembersListFragment, TAG_GROUP_MEMBERS)
                         .commit();
-            } else {
-                getLoaderManager().initLoader(LOADER_GROUP_MEMBERS, null, mGroupMemberCallbacks);
             }
             mMembersListFragment.setListener(this);
             if (mGroupMetadata != null && mGroupMetadata.editable) {
@@ -311,25 +335,13 @@
     @Override
     public boolean onPrepareOptionsMenu(Menu menu) {
         final boolean isSelectionMode = mActionBarAdapter.isSelectionMode();
-        final boolean isSearchMode = mActionBarAdapter.isSearchMode();
-
         final boolean isGroupEditable = mGroupMetadata != null && mGroupMetadata.editable;
         final boolean isGroupReadOnly = mGroupMetadata != null && mGroupMetadata.readOnly;
 
-        setVisible(menu, R.id.menu_add,
-                isGroupEditable && !isSelectionMode && !isSearchMode);
-
-        setVisible(menu, R.id.menu_search,
-                isGroupEditable && !isSelectionMode && !isSearchMode);
-
-        setVisible(menu, R.id.menu_rename_group,
-                isGroupEditable && !isSelectionMode && !isSearchMode);
-
-        setVisible(menu, R.id.menu_delete_group,
-                !isGroupReadOnly && !isSelectionMode && !isSearchMode);
-
-        setVisible(menu, R.id.menu_remove_from_group,
-                isGroupEditable && isSelectionMode);
+        setVisible(menu, R.id.menu_add, isGroupEditable && !isSelectionMode);
+        setVisible(menu, R.id.menu_rename_group, isGroupEditable && !isSelectionMode);
+        setVisible(menu, R.id.menu_delete_group, !isGroupReadOnly && !isSelectionMode);
+        setVisible(menu, R.id.menu_remove_from_group, isGroupEditable && isSelectionMode);
 
         return true;
     }
@@ -353,17 +365,11 @@
                 intent.setType(ContactsContract.Groups.CONTENT_ITEM_TYPE);
                 intent.putExtra(UiIntentActions.GROUP_ACCOUNT_WITH_DATA_SET,
                         mGroupMetadata.createAccountWithDataSet());
-                intent.putExtra(UiIntentActions.GROUP_RAW_CONTACT_IDS,
-                        getExistingGroupMemberRawContactIds());
+                intent.putExtra(UiIntentActions.GROUP_CONTACT_IDS,
+                        getExistingGroupMemberContactIds());
                 startActivityForResult(intent, RESULT_GROUP_ADD_MEMBER);
                 return true;
             }
-            case R.id.menu_search: {
-                if (mActionBarAdapter != null) {
-                    mActionBarAdapter.setSearchMode(true);
-                }
-                return true;
-            }
             case R.id.menu_rename_group: {
                 GroupNameEditDialogFragment.showUpdateDialog(
                         getFragmentManager(), TAG_GROUP_NAME_EDIT_DIALOG, mGroupMetadata.groupName);
@@ -385,15 +391,15 @@
         return super.onOptionsItemSelected(item);
     }
 
-    private ArrayList<String> getExistingGroupMemberRawContactIds() {
-        final ArrayList<String> rawContactIds = new ArrayList<>();
+    private ArrayList<String> getExistingGroupMemberContactIds() {
+        final ArrayList<String> contactIds = new ArrayList<>();
         final Cursor cursor = mMembersListFragment.getAdapter().getCursor(/* partition */ 0);
         if (cursor != null && cursor.moveToFirst()) {
             do {
-                rawContactIds.add(cursor.getString(GroupMembersQuery.RAW_CONTACT_ID));
+                contactIds.add(cursor.getString(GroupMembersQuery.CONTACT_ID));
             } while (cursor.moveToNext());
         }
-        return rawContactIds;
+        return contactIds;
     }
 
     private void deleteGroup() {
@@ -408,7 +414,6 @@
         }
     }
 
-    // TODO(wjang): replace this with group events
     private void logListEvent() {
         Logger.logListEvent(
                 ListEvent.ActionType.REMOVE_LABEL,
@@ -446,30 +451,14 @@
         }
     }
 
-
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         if (requestCode == RESULT_GROUP_ADD_MEMBER && resultCode == RESULT_OK && data != null) {
-            final Uri rawContactUri = data.getData();
-            if (rawContactUri != null) {
-                long rawContactId = -1;
-                try {
-                    rawContactId = Long.parseLong(rawContactUri.getLastPathSegment());
-                } catch (NumberFormatException ignored) {}
-                if (rawContactId < 0) {
-                    Toast.makeText(this, R.string.groupSavedErrorToast, Toast.LENGTH_SHORT).show();
-                    Log.w(TAG, "Failed to parse ID from pick group member result uri " +
-                            rawContactUri);
-                    return;
-                }
-                final long[] rawContactIdsToAdd = new long[1];
-                rawContactIdsToAdd[0] = rawContactId;
-                final Intent intent = ContactSaveService.createGroupUpdateIntent(
-                        GroupMembersActivity.this, mGroupMetadata.groupId, /* newLabel */ null,
-                        rawContactIdsToAdd, /* rawContactIdsToRemove */ null,
-                        GroupMembersActivity.class, GroupMembersActivity.ACTION_ADD_TO_GROUP);
-                startService(intent);
-            }
+            final long contactId = data.getLongExtra(
+                    UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, -1);
+            new AddGroupMembersAsyncTask(this, contactId, mGroupMetadata.groupId,
+                    mGroupMetadata.accountName, mGroupMetadata.accountType)
+                    .execute();
         }
     }
 
@@ -512,11 +501,6 @@
     @Override
     public void onAction(int action) {
         switch (action) {
-            case ActionBarAdapter.Listener.Action.START_SEARCH_MODE:
-                mActionBarAdapter.setSearchMode(true);
-                invalidateOptionsMenu();
-                showFabWithAnimation(/* showFabWithAnimation = */ false);
-                break;
             case ActionBarAdapter.Listener.Action.START_SELECTION_MODE:
                 if (mMembersListFragment != null) {
                     mMembersListFragment.displayCheckBoxes(true);
@@ -539,7 +523,7 @@
     }
 
     private void showFabWithAnimation(boolean showFab) {
-        // TODO(wjang): b/28497108
+        // TODO: b/28497108
     }
 
     @Override
@@ -598,63 +582,12 @@
     @Override
     public void onGroupMetadataLoaded(GroupMetadata groupMetadata) {
         mGroupMetadata = groupMetadata;
-
         if (!mIsInsertAction) {
             getSupportActionBar().setTitle(mGroupMetadata.groupName);
         }
-
-        bindAutocompleteTextView();
-        getLoaderManager().initLoader(LOADER_GROUP_MEMBERS, null, mGroupMemberCallbacks);
-
         invalidateOptionsMenu();
     }
 
-    private void bindAutocompleteTextView() {
-        final AutoCompleteTextView autoCompleteTextView =
-                (AutoCompleteTextView) mActionBarAdapter.getSearchView();
-        if (autoCompleteTextView == null) return;
-        mAutoCompleteAdapter = createAutocompleteAdapter();
-        autoCompleteTextView.setAdapter(mAutoCompleteAdapter);
-        autoCompleteTextView.setOnItemClickListener(new OnItemClickListener() {
-            @Override
-            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-                final SuggestedMember member = (SuggestedMember) view.getTag();
-                if (member == null) {
-                    return;
-                }
-                final long[] rawContactIdsToAdd = new long[1];
-                rawContactIdsToAdd[0] = member.getRawContactId();
-                final Intent intent = ContactSaveService.createGroupUpdateIntent(
-                        GroupMembersActivity.this, mGroupMetadata.groupId, /* newLabel */ null,
-                        rawContactIdsToAdd, /* rawContactIdsToRemove */ null,
-                        GroupMembersActivity.class, ACTION_ADD_TO_GROUP);
-                startService(intent);
-
-                // Update the autocomplete adapter so the contact doesn't get suggested again
-                mAutoCompleteAdapter.addNewMember(member.getContactId());
-
-                // Clear out the text field
-                autoCompleteTextView.setText("");
-            }
-        });
-    }
-
-    private SuggestedMemberListAdapter createAutocompleteAdapter() {
-        final SuggestedMemberListAdapter adapter = new SuggestedMemberListAdapter(
-                this, android.R.layout.simple_dropdown_item_1line);
-        adapter.setContentResolver(this.getContentResolver());
-        adapter.setAccountType(mGroupMetadata.accountType);
-        adapter.setAccountName(mGroupMetadata.accountName);
-        adapter.setDataSet(mGroupMetadata.dataSet);
-        return adapter;
-    }
-
-    private void bindAutocompleteGroupMembers(List<Member> members) {
-        if (mAutoCompleteAdapter != null) {
-            mAutoCompleteAdapter.updateExistingMembersList(members);
-        }
-    }
-
     @Override
     public void onGroupMetadataLoadFailed() {
         setResultCanceledAndFinish(R.string.groupLoadErrorToast);
diff --git a/src/com/android/contacts/editor/AccountsChangedBroadcastReceiver.java b/src/com/android/contacts/editor/AccountsChangedBroadcastReceiver.java
new file mode 100644
index 0000000..55300d5
--- /dev/null
+++ b/src/com/android/contacts/editor/AccountsChangedBroadcastReceiver.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 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.editor;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.contacts.R;
+import com.android.contacts.common.model.AccountTypeManager;
+import com.android.contacts.common.model.account.AccountWithDataSet;
+
+import java.util.List;
+
+/**
+ * This class is to fix the bug that no prompt is seen for multiple accounts while creating new
+ * contacts. By registering a BroadcastReceiver statically, we detect the changes of accounts by
+ * receiving the message "android.accounts.LOGIN_ACCOUNTS_CHANGED". If the BroadcastReceiver gets
+ * this message, it will get the default account from the SharedPreference and compare current
+ * accounts with the default account. At last, it will renew the default account in the
+ * SharedPreference if necessary.
+ */
+public class AccountsChangedBroadcastReceiver extends BroadcastReceiver {
+    final String TAG = "AccountsChanged";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        Context appContext = context.getApplicationContext();
+        final ContactEditorUtils contactEditorUtils = ContactEditorUtils.getInstance(appContext);
+        final String defaultAccountKey = appContext.getResources().getString(
+                R.string.contact_editor_default_account_key);
+        final SharedPreferences pref = appContext.getSharedPreferences(
+                appContext.getPackageName(), Context.MODE_PRIVATE);
+        final String defaultAccountString = pref.getString(defaultAccountKey, null);
+
+        if (!TextUtils.isEmpty(defaultAccountString)) {
+            AccountWithDataSet defaultAccount;
+            try {
+                defaultAccount = AccountWithDataSet.unstringify(defaultAccountString);
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "Invalid string in SharedPreference", e);
+                contactEditorUtils.saveDefaultAndAllAccounts(null);
+                return;
+            }
+
+            final AccountTypeManager accountTypeManager = AccountTypeManager.getInstance(
+                    appContext);
+            final List<AccountWithDataSet> accounts = accountTypeManager.getAccounts(true);
+            // Delete default account pref if it has been deleted.
+            if (accounts == null || accounts.size() < 1 || !accounts.contains(defaultAccount)) {
+                contactEditorUtils.saveDefaultAndAllAccounts(null);
+            }
+        }
+    }
+}
diff --git a/src/com/android/contacts/editor/ContactEditorBaseFragment.java b/src/com/android/contacts/editor/ContactEditorBaseFragment.java
index 4182e1f..c1e5af8 100644
--- a/src/com/android/contacts/editor/ContactEditorBaseFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorBaseFragment.java
@@ -16,35 +16,6 @@
 
 package com.android.contacts.editor;
 
-import com.android.contacts.common.logging.ScreenEvent.ScreenType;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.GroupMetaDataLoader;
-import com.android.contacts.R;
-import com.android.contacts.activities.ContactEditorAccountsChangedActivity;
-import com.android.contacts.activities.ContactEditorBaseActivity;
-import com.android.contacts.activities.ContactEditorBaseActivity.ContactEditor;
-import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.common.model.Contact;
-import com.android.contacts.common.model.ContactLoader;
-import com.android.contacts.common.model.RawContact;
-import com.android.contacts.common.model.RawContactDelta;
-import com.android.contacts.common.model.RawContactDeltaList;
-import com.android.contacts.common.model.RawContactModifier;
-import com.android.contacts.common.model.ValuesDelta;
-import com.android.contacts.common.model.account.AccountType;
-import com.android.contacts.common.model.account.AccountWithDataSet;
-import com.android.contacts.common.util.ImplicitIntentsUtil;
-import com.android.contacts.common.util.MaterialColorMapUtils;
-import com.android.contacts.editor.AggregationSuggestionEngine.Suggestion;
-import com.android.contacts.list.UiIntentActions;
-import com.android.contacts.quickcontact.QuickContactActivity;
-import com.android.contacts.util.HelpUtils;
-import com.android.contacts.util.PhoneCapabilityTester;
-import com.android.contacts.util.UiClosables;
-
 import android.accounts.Account;
 import android.app.Activity;
 import android.app.Fragment;
@@ -84,6 +55,34 @@
 import android.widget.ListPopupWindow;
 import android.widget.Toast;
 
+import com.android.contacts.ContactSaveService;
+import com.android.contacts.GroupMetaDataLoader;
+import com.android.contacts.R;
+import com.android.contacts.activities.ContactEditorAccountsChangedActivity;
+import com.android.contacts.activities.ContactEditorBaseActivity;
+import com.android.contacts.activities.ContactEditorBaseActivity.ContactEditor;
+import com.android.contacts.common.logging.ScreenEvent.ScreenType;
+import com.android.contacts.common.model.AccountTypeManager;
+import com.android.contacts.common.model.Contact;
+import com.android.contacts.common.model.ContactLoader;
+import com.android.contacts.common.model.RawContact;
+import com.android.contacts.common.model.RawContactDelta;
+import com.android.contacts.common.model.RawContactDeltaList;
+import com.android.contacts.common.model.RawContactModifier;
+import com.android.contacts.common.model.ValuesDelta;
+import com.android.contacts.common.model.account.AccountType;
+import com.android.contacts.common.model.account.AccountWithDataSet;
+import com.android.contacts.common.util.ImplicitIntentsUtil;
+import com.android.contacts.common.util.MaterialColorMapUtils;
+import com.android.contacts.editor.AggregationSuggestionEngine.Suggestion;
+import com.android.contacts.list.UiIntentActions;
+import com.android.contacts.quickcontact.QuickContactActivity;
+import com.android.contacts.util.HelpUtils;
+import com.android.contacts.util.PhoneCapabilityTester;
+import com.android.contacts.util.UiClosables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -1472,6 +1471,7 @@
                             QuickContactActivity.MODE_FULLY_EXPANDED);
                     resultIntent.putExtra(QuickContactActivity.EXTRA_PREVIOUS_SCREEN_TYPE,
                             ScreenType.EDITOR);
+                    resultIntent.putExtra(QuickContactActivity.EXTRA_CONTACT_EDITED, true);
                 } else {
                     resultIntent = null;
                 }
diff --git a/src/com/android/contacts/group/GroupMembersListAdapter.java b/src/com/android/contacts/group/GroupMembersListAdapter.java
index 86e75b1..0f3ae8a 100644
--- a/src/com/android/contacts/group/GroupMembersListAdapter.java
+++ b/src/com/android/contacts/group/GroupMembersListAdapter.java
@@ -28,6 +28,7 @@
 import android.view.ViewGroup;
 
 import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
+import com.android.contacts.common.R;
 import com.android.contacts.common.list.ContactListItemView;
 import com.android.contacts.common.list.MultiSelectEntryContactListAdapter;
 import com.android.contacts.common.preference.ContactsPreferences;
@@ -71,7 +72,7 @@
 
     public GroupMembersListAdapter(Context context) {
         super(context, GroupMembersQuery.RAW_CONTACT_ID);
-        mUnknownNameText = context.getText(android.R.string.unknownName);
+        mUnknownNameText = context.getText(R.string.missing_name);
     }
 
     /** Sets the ID of the group whose members will be displayed. */
diff --git a/src/com/android/contacts/group/Member.java b/src/com/android/contacts/group/Member.java
deleted file mode 100644
index ad6f9b2..0000000
--- a/src/com/android/contacts/group/Member.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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.group;
-
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.provider.ContactsContract.Contacts;
-
-import com.google.common.base.Objects;
-
-/** A member of the group currently being displayed to the user. */
-public class Member implements Parcelable {
-
-    public static final Parcelable.Creator<Member> CREATOR = new Parcelable.Creator<Member>() {
-        @Override
-        public Member createFromParcel(Parcel in) {
-            return new Member(in);
-        }
-
-        @Override
-        public Member[] newArray(int size) {
-            return new Member[size];
-        }
-    };
-
-    private final long mRawContactId;
-    private final long mContactId;
-    private final Uri mLookupUri;
-    private final String mDisplayName;
-    private final Uri mPhotoUri;
-    private final String mLookupKey;
-    private final long mPhotoId;
-
-    public Member(long rawContactId, String lookupKey, long contactId, String displayName,
-            String photoUri, long photoId) {
-        mRawContactId = rawContactId;
-        mContactId = contactId;
-        mLookupKey = lookupKey;
-        mLookupUri = Contacts.getLookupUri(contactId, lookupKey);
-        mDisplayName = displayName;
-        mPhotoUri = (photoUri != null) ? Uri.parse(photoUri) : null;
-        mPhotoId = photoId;
-    }
-
-    public long getRawContactId() {
-        return mRawContactId;
-    }
-
-    public long getContactId() {
-        return mContactId;
-    }
-
-    public Uri getLookupUri() {
-        return mLookupUri;
-    }
-
-    public String getLookupKey() {
-        return mLookupKey;
-    }
-
-    public String getDisplayName() {
-        return mDisplayName;
-    }
-
-    public Uri getPhotoUri() {
-        return mPhotoUri;
-    }
-
-    public long getPhotoId() {
-        return mPhotoId;
-    }
-
-    @Override
-    public boolean equals(Object object) {
-        if (object instanceof Member) {
-            Member otherMember = (Member) object;
-            return Objects.equal(mLookupUri, otherMember.getLookupUri());
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return mLookupUri == null ? 0 : mLookupUri.hashCode();
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeLong(mRawContactId);
-        dest.writeLong(mContactId);
-        dest.writeParcelable(mLookupUri, flags);
-        dest.writeString(mLookupKey);
-        dest.writeString(mDisplayName);
-        dest.writeParcelable(mPhotoUri, flags);
-        dest.writeLong(mPhotoId);
-    }
-
-    private Member(Parcel in) {
-        mRawContactId = in.readLong();
-        mContactId = in.readLong();
-        mLookupUri = in.readParcelable(getClass().getClassLoader());
-        mLookupKey = in.readString();
-        mDisplayName = in.readString();
-        mPhotoUri = in.readParcelable(getClass().getClassLoader());
-        mPhotoId = in.readLong();
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/contacts/group/SuggestedMemberListAdapter.java b/src/com/android/contacts/group/SuggestedMemberListAdapter.java
deleted file mode 100644
index e2756c6..0000000
--- a/src/com/android/contacts/group/SuggestedMemberListAdapter.java
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * 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.group;
-
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.Context;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.net.Uri;
-import android.provider.ContactsContract.CommonDataKinds.Email;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
-import android.provider.ContactsContract.Contacts.Data;
-import android.provider.ContactsContract.RawContacts;
-import android.provider.ContactsContract.RawContactsEntity;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.AutoCompleteTextView;
-import android.widget.Filter;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.contacts.R;
-import com.android.contacts.common.ContactPhotoManager;
-import com.android.contacts.group.SuggestedMemberListAdapter.SuggestedMember;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * This adapter provides suggested contacts that can be added to a group for an
- * {@link AutoCompleteTextView} within the group editor.
- */
-public class SuggestedMemberListAdapter extends ArrayAdapter<SuggestedMember> {
-
-    private static final String[] PROJECTION_FILTERED_MEMBERS = new String[] {
-        RawContacts._ID,                        // 0
-        RawContacts.CONTACT_ID,                 // 1
-        RawContacts.DISPLAY_NAME_PRIMARY        // 2
-    };
-
-    private static final int RAW_CONTACT_ID_COLUMN_INDEX = 0;
-    private static final int CONTACT_ID_COLUMN_INDEX = 1;
-    private static final int DISPLAY_NAME_PRIMARY_COLUMN_INDEX = 2;
-
-    private static final String[] PROJECTION_MEMBER_DATA = new String[] {
-        RawContacts._ID,                        // 0
-        RawContacts.CONTACT_ID,                 // 1
-        Data.MIMETYPE,                          // 2
-        Data.DATA1,                             // 3
-        Photo.PHOTO,                            // 4
-    };
-
-    private static final int ID_INDEX = 0;
-    private static final int MIMETYPE_COLUMN_INDEX = 2;
-    private static final int DATA_COLUMN_INDEX = 3;
-    private static final int PHOTO_COLUMN_INDEX = 4;
-
-    private Filter mFilter;
-    private ContentResolver mContentResolver;
-    private LayoutInflater mInflater;
-    private ContactPhotoManager mPhotoManager;
-
-    private String mAccountType;
-    private String mAccountName;
-    private String mDataSet;
-
-    // TODO: Make this a Map for better performance when we check if a new contact is in the list
-    // or not
-    private final List<Long> mExistingMemberContactIds = new ArrayList<Long>();
-
-    private static final int SUGGESTIONS_LIMIT = 5;
-
-    public SuggestedMemberListAdapter(Context context, int textViewResourceId) {
-        super(context, textViewResourceId);
-        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        mPhotoManager = ContactPhotoManager.getInstance(context);
-    }
-
-    public void setAccountType(String accountType) {
-        mAccountType = accountType;
-    }
-
-    public void setAccountName(String accountName) {
-        mAccountName = accountName;
-    }
-
-    public void setDataSet(String dataSet) {
-        mDataSet = dataSet;
-    }
-
-    public void setContentResolver(ContentResolver resolver) {
-        mContentResolver = resolver;
-    }
-
-    public void updateExistingMembersList(List<Member> list) {
-        mExistingMemberContactIds.clear();
-        for (Member member : list) {
-            mExistingMemberContactIds.add(member.getContactId());
-        }
-    }
-
-    public void addNewMember(long contactId) {
-        mExistingMemberContactIds.add(contactId);
-    }
-
-    public void removeMember(long contactId) {
-        if (mExistingMemberContactIds.contains(contactId)) {
-            mExistingMemberContactIds.remove(contactId);
-        }
-    }
-
-    @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
-        View result = convertView;
-        if (result == null) {
-            result = mInflater.inflate(R.layout.group_member_suggestion, parent, false);
-        }
-        // TODO: Use a viewholder
-        SuggestedMember member = getItem(position);
-        TextView text1 = (TextView) result.findViewById(R.id.text1);
-        TextView text2 = (TextView) result.findViewById(R.id.text2);
-        ImageView icon = (ImageView) result.findViewById(R.id.icon);
-        text1.setText(member.getDisplayName());
-        if (member.hasExtraInfo()) {
-            text2.setText(member.getExtraInfo());
-        } else {
-            text2.setVisibility(View.GONE);
-        }
-        byte[] byteArray = member.getPhotoByteArray();
-        if (byteArray == null) {
-            final Uri contactLookupUri = RawContacts.getContactLookupUri(mContentResolver,
-                    ContentUris.withAppendedId(RawContacts.CONTENT_URI, member.getContactId()));
-            final String imageRequestIdentifier = contactLookupUri == null
-                    ? null : contactLookupUri.toString();
-            GroupUtil.bindPhoto(mPhotoManager, icon, member.getPhotoId(),
-                /* photoUri */ null, member.getDisplayName(), imageRequestIdentifier);
-        } else {
-            Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
-            icon.setImageBitmap(frameBitmapInCircle(bitmap));
-        }
-        result.setTag(member);
-        return result;
-    }
-
-    private static Bitmap frameBitmapInCircle(Bitmap input) {
-        // Crop the image if not squared.
-        final int targetDiameter = input.getWidth();
-        final Bitmap scaled = Bitmap.createScaledBitmap(
-                input, targetDiameter, targetDiameter, /* filter */ false);
-        int inputWidth = scaled.getWidth();
-        int inputHeight = scaled.getHeight();
-        int targetX, targetY, targetSize;
-        if (inputWidth >= inputHeight) {
-            targetX = inputWidth / 2 - inputHeight / 2;
-            targetY = 0;
-            targetSize = inputHeight;
-        } else {
-            targetX = 0;
-            targetY = inputHeight / 2 - inputWidth / 2;
-            targetSize = inputWidth;
-        }
-
-        // Create an output bitmap and a canvas to draw on it.
-        final Bitmap output = Bitmap.createBitmap(targetSize, targetSize, Bitmap.Config.ARGB_8888);
-        final Canvas canvas = new Canvas(output);
-
-        // Create a black paint to draw the mask.
-        final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
-        paint.setColor(Color.BLACK);
-
-        // Draw a circle.
-        canvas.drawCircle(targetDiameter / 2, targetDiameter / 2, targetDiameter / 2, paint);
-
-        // Replace the black parts of the mask with the input image.
-        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
-        canvas.drawBitmap(scaled, targetX /* left */, targetY /* top */, paint);
-
-        return output;
-    }
-
-    @Override
-    public Filter getFilter() {
-        if (mFilter == null) {
-            mFilter = new SuggestedMemberFilter();
-        }
-        return mFilter;
-    }
-
-    /**
-     * This filter queries for raw contacts that match the given account name and account type,
-     * as well as the search query.
-     */
-    public class SuggestedMemberFilter extends Filter {
-
-        @Override
-        protected FilterResults performFiltering(CharSequence prefix) {
-            FilterResults results = new FilterResults();
-            if (mContentResolver == null || TextUtils.isEmpty(prefix)) {
-                return results;
-            }
-
-            // Create a list to store the suggested contacts (which will be alphabetically ordered),
-            // but also keep a map of raw contact IDs to {@link SuggestedMember}s to make it easier
-            // to add supplementary data to the contact (photo, phone, email) to the members based
-            // on raw contact IDs after the second query is completed.
-            List<SuggestedMember> suggestionsList = new ArrayList<SuggestedMember>();
-            HashMap<Long, SuggestedMember> suggestionsMap = new HashMap<Long, SuggestedMember>();
-
-            // First query for all the raw contacts that match the given search query
-            // and have the same account name and type as specified in this adapter
-            String searchQuery = prefix.toString() + "%";
-            String accountClause = RawContacts.ACCOUNT_NAME + "=? AND " +
-                    RawContacts.ACCOUNT_TYPE + "=?";
-            String[] args;
-            if (mDataSet == null) {
-                accountClause += " AND " + RawContacts.DATA_SET + " IS NULL";
-                args = new String[] {mAccountName, mAccountType, searchQuery, searchQuery};
-            } else {
-                accountClause += " AND " + RawContacts.DATA_SET + "=?";
-                args = new String[] {
-                        mAccountName, mAccountType, mDataSet, searchQuery, searchQuery
-                };
-            }
-
-            Cursor cursor = mContentResolver.query(
-                    RawContacts.CONTENT_URI, PROJECTION_FILTERED_MEMBERS,
-                    accountClause + " AND (" +
-                    RawContacts.DISPLAY_NAME_PRIMARY + " LIKE ? OR " +
-                    RawContacts.DISPLAY_NAME_ALTERNATIVE + " LIKE ? )",
-                    args, RawContacts.DISPLAY_NAME_PRIMARY + " COLLATE LOCALIZED ASC");
-
-            if (cursor == null) {
-                return results;
-            }
-
-            // Read back the results from the cursor and filter out existing group members.
-            // For valid suggestions, add them to the hash map of suggested members.
-            try {
-                cursor.moveToPosition(-1);
-                while (cursor.moveToNext() && suggestionsMap.keySet().size() < SUGGESTIONS_LIMIT) {
-                    long rawContactId = cursor.getLong(RAW_CONTACT_ID_COLUMN_INDEX);
-                    long contactId = cursor.getLong(CONTACT_ID_COLUMN_INDEX);
-                    // Filter out contacts that have already been added to this group
-                    if (mExistingMemberContactIds.contains(contactId)) {
-                        continue;
-                    }
-                    // Otherwise, add the contact as a suggested new group member
-                    String displayName = cursor.getString(DISPLAY_NAME_PRIMARY_COLUMN_INDEX);
-                    SuggestedMember member = new SuggestedMember(rawContactId, displayName,
-                            contactId);
-                    // Store the member in the list of suggestions and add it to the hash map too.
-                    suggestionsList.add(member);
-                    suggestionsMap.put(rawContactId, member);
-                }
-            } finally {
-                cursor.close();
-            }
-
-            int numSuggestions = suggestionsMap.keySet().size();
-            if (numSuggestions == 0) {
-                return results;
-            }
-
-            // Create a part of the selection string for the next query with the pattern (?, ?, ?)
-            // where the number of comma-separated question marks represent the number of raw
-            // contact IDs found in the previous query (while respective the SUGGESTION_LIMIT)
-            final StringBuilder rawContactIdSelectionBuilder = new StringBuilder();
-            final String[] questionMarks = new String[numSuggestions];
-            Arrays.fill(questionMarks, "?");
-            rawContactIdSelectionBuilder.append(RawContacts._ID + " IN (")
-                    .append(TextUtils.join(",", questionMarks))
-                    .append(")");
-
-            // Construct the selection args based on the raw contact IDs we're interested in
-            // (as well as the photo, email, and phone mimetypes)
-            List<String> selectionArgs = new ArrayList<String>();
-            selectionArgs.add(Photo.CONTENT_ITEM_TYPE);
-            selectionArgs.add(Email.CONTENT_ITEM_TYPE);
-            selectionArgs.add(Phone.CONTENT_ITEM_TYPE);
-            for (Long rawContactId : suggestionsMap.keySet()) {
-                selectionArgs.add(String.valueOf(rawContactId));
-            }
-
-            // Perform a second query to retrieve a photo and possibly a phone number or email
-            // address for the suggested contact
-            Cursor memberDataCursor = mContentResolver.query(
-                    RawContactsEntity.CONTENT_URI, PROJECTION_MEMBER_DATA,
-                    "(" + Data.MIMETYPE + "=? OR " + Data.MIMETYPE + "=? OR " + Data.MIMETYPE +
-                    "=?) AND " + rawContactIdSelectionBuilder.toString(),
-                    selectionArgs.toArray(new String[0]), null);
-
-            if (memberDataCursor != null) {
-                try {
-                    memberDataCursor.moveToPosition(-1);
-                    while (memberDataCursor.moveToNext()) {
-                        long rawContactId = memberDataCursor.getLong(RAW_CONTACT_ID_COLUMN_INDEX);
-                        SuggestedMember member = suggestionsMap.get(rawContactId);
-                        if (member == null) {
-                            continue;
-                        }
-                        String mimetype = memberDataCursor.getString(MIMETYPE_COLUMN_INDEX);
-                        if (Photo.CONTENT_ITEM_TYPE.equals(mimetype)) {
-                            // Set photo
-                            member.setPhotoId(memberDataCursor.getLong(ID_INDEX));
-                            byte[] bitmapArray = memberDataCursor.getBlob(PHOTO_COLUMN_INDEX);
-                            member.setPhotoByteArray(bitmapArray);
-                        } else if (Email.CONTENT_ITEM_TYPE.equals(mimetype) ||
-                                Phone.CONTENT_ITEM_TYPE.equals(mimetype)) {
-                            // Set at most 1 extra piece of contact info that can be a phone number or
-                            // email
-                            if (!member.hasExtraInfo()) {
-                                String info = memberDataCursor.getString(DATA_COLUMN_INDEX);
-                                member.setExtraInfo(info);
-                            }
-                        }
-                    }
-                } finally {
-                    memberDataCursor.close();
-                }
-            }
-            results.values = suggestionsList;
-            return results;
-        }
-
-        @Override
-        protected void publishResults(CharSequence constraint, FilterResults results) {
-            @SuppressWarnings("unchecked")
-            List<SuggestedMember> suggestionsList = (List<SuggestedMember>) results.values;
-            if (suggestionsList == null) {
-                return;
-            }
-
-            // Clear out the existing suggestions in this adapter
-            clear();
-
-            // Add all the suggested members to this adapter
-            for (SuggestedMember member : suggestionsList) {
-                add(member);
-            }
-
-            notifyDataSetChanged();
-        }
-    }
-
-    /**
-     * This represents a single contact that is a suggestion for the user to add to a group.
-     */
-    // TODO: Merge this with the {@link GroupEditorFragment} Member class once we can find the
-    // lookup URI for this contact using the autocomplete filter queries
-    public class SuggestedMember {
-
-        private long mRawContactId;
-        private long mContactId;
-        private String mDisplayName;
-
-        private String mExtraInfo;
-        private byte[] mPhoto;
-        private long mPhotoId;
-
-        public SuggestedMember(long rawContactId, String displayName, long contactId) {
-            mRawContactId = rawContactId;
-            mDisplayName = displayName;
-            mContactId = contactId;
-        }
-
-        public String getDisplayName() {
-            return mDisplayName;
-        }
-
-        public String getExtraInfo() {
-            return mExtraInfo;
-        }
-
-        public long getRawContactId() {
-            return mRawContactId;
-        }
-
-        public long getContactId() {
-            return mContactId;
-        }
-
-        public byte[] getPhotoByteArray() {
-            return mPhoto;
-        }
-
-        public long getPhotoId() {
-            return mPhotoId;
-        }
-
-        public boolean hasExtraInfo() {
-            return mExtraInfo != null;
-        }
-
-        /**
-         * Set a phone number or email to distinguish this contact
-         */
-        public void setExtraInfo(String info) {
-            mExtraInfo = info;
-        }
-
-        public void setPhotoByteArray(byte[] photo) {
-            mPhoto = photo;
-        }
-
-        public void setPhotoId(long photoId) {
-            mPhotoId = photoId;
-        }
-
-        @Override
-        public String toString() {
-            return getDisplayName();
-        }
-    }
-}
diff --git a/src/com/android/contacts/list/ContactsIntentResolver.java b/src/com/android/contacts/list/ContactsIntentResolver.java
index ded72c2..4bd131e 100644
--- a/src/com/android/contacts/list/ContactsIntentResolver.java
+++ b/src/com/android/contacts/list/ContactsIntentResolver.java
@@ -97,7 +97,7 @@
                 request.setAccountWithDataSet(intent.<AccountWithDataSet> getParcelableExtra(
                         UiIntentActions.GROUP_ACCOUNT_WITH_DATA_SET));
                 request.setRawContactIds(intent.getStringArrayListExtra(
-                        UiIntentActions.GROUP_RAW_CONTACT_IDS));
+                        UiIntentActions.GROUP_CONTACT_IDS));
             }
         } else if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {
             String component = intent.getComponent().getClassName();
diff --git a/src/com/android/contacts/list/GroupMemberPickListAdapter.java b/src/com/android/contacts/list/GroupMemberPickListAdapter.java
deleted file mode 100644
index d25aafd..0000000
--- a/src/com/android/contacts/list/GroupMemberPickListAdapter.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2016 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.list;
-
-import android.content.Context;
-import android.content.CursorLoader;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.RawContacts;
-import android.text.TextUtils;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
-import com.android.contacts.common.list.ContactEntryListAdapter;
-import com.android.contacts.common.list.ContactListItemView;
-import com.android.contacts.common.model.account.AccountWithDataSet;
-import com.android.contacts.common.preference.ContactsPreferences;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Adapter for raw contacts owned by an account that are not already members of a given group.
- */
-public class GroupMemberPickListAdapter extends ContactEntryListAdapter {
-
-    static class GroupMembersQuery {
-
-        private static final String[] PROJECTION_PRIMARY = new String[] {
-                Data.RAW_CONTACT_ID,             // 0
-                Data.CONTACT_ID,                 // 1
-                Data.DISPLAY_NAME_PRIMARY,       // 2
-                // Dummy columns overwritten by the cursor wrapper
-                Data.PHOTO_ID,                   // 3
-                Data.LOOKUP_KEY                  // 4
-        };
-
-        private static final String[] PROJECTION_ALTERNATIVE = new String[] {
-                Data.RAW_CONTACT_ID,             // 0
-                Data.CONTACT_ID,                 // 1
-                Data.DISPLAY_NAME_ALTERNATIVE,   // 2
-                // Dummy columns overwritten by the cursor wrapper
-                Data.PHOTO_ID,                   // 3
-                Data.LOOKUP_KEY                  // 4
-        };
-
-        static final int RAW_CONTACT_ID = 0;
-        static final int CONTACT_ID = 1;
-        static final int CONTACT_DISPLAY_NAME = 2;
-        // Provided by the cursor wrapper.
-        static final int CONTACT_PHOTO_ID = 3;
-        // Provided by the cursor wrapper.
-        static final int CONTACT_LOOKUP_KEY = 4;
-
-        private GroupMembersQuery() {
-        }
-    }
-
-    private AccountWithDataSet mAccount;
-    private final Set<String> mRawContactIds = new HashSet<>();
-
-    private final CharSequence mUnknownNameText;
-
-    public GroupMemberPickListAdapter(Context context) {
-        super(context);
-        mUnknownNameText = context.getText(android.R.string.unknownName);
-    }
-
-    public GroupMemberPickListAdapter setAccount(AccountWithDataSet account) {
-        mAccount = account;
-        return this;
-    }
-
-    public GroupMemberPickListAdapter setRawContactIds(ArrayList<String> rawContactIds) {
-        mRawContactIds.clear();
-        mRawContactIds.addAll(rawContactIds);
-        return this;
-    }
-
-    @Override
-    public String getContactDisplayName(int position) {
-        final Cursor cursor = (Cursor) getItem(position);
-        return cursor.getString(GroupMembersQuery.CONTACT_DISPLAY_NAME);
-    }
-
-    @Override
-    public void configureLoader(CursorLoader loader, long directoryId) {
-        final Uri uri = Data.CONTENT_URI.buildUpon()
-                .appendQueryParameter(Data.VISIBLE_CONTACTS_ONLY, "true")
-                .build();
-        loader.setUri(uri);
-        loader.setProjection(
-                getContactNameDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY
-                        ? GroupMembersQuery.PROJECTION_PRIMARY
-                        : GroupMembersQuery.PROJECTION_ALTERNATIVE);
-        loader.setSelection(getSelection());
-        loader.setSelectionArgs(getSelectionArgs());
-        loader.setSortOrder(getSortOrder() == ContactsPreferences.SORT_ORDER_PRIMARY
-                ? Data.SORT_KEY_PRIMARY : Data.SORT_KEY_ALTERNATIVE
-                + " COLLATE LOCALIZED ASC");
-    }
-
-    private String getSelection() {
-        // Select raw contacts by account
-        String result = RawContacts.ACCOUNT_NAME + "=? AND " + RawContacts.ACCOUNT_TYPE + "=? AND "
-                + Data.MIMETYPE + "=? AND ";
-        if (TextUtils.isEmpty(mAccount.dataSet)) {
-            result += Data.DATA_SET + " IS NULL";
-        } else {
-            result += Data.DATA_SET + "=?";
-        }
-        return result;
-    }
-
-    private String[] getSelectionArgs() {
-        final ArrayList<String> result = new ArrayList<>();
-        result.add(mAccount.name);
-        result.add(mAccount.type);
-        result.add(GroupMembership.CONTENT_ITEM_TYPE);
-        if (!TextUtils.isEmpty(mAccount.dataSet)) result.add(mAccount.dataSet);
-        return result.toArray(new String[0]);
-    }
-
-    public Uri getRawContactUri(int position) {
-        final Cursor cursor = (Cursor) getItem(position);
-        final long rawContactId = cursor.getLong(GroupMembersQuery.RAW_CONTACT_ID);
-        return Data.CONTENT_URI.buildUpon()
-                .appendPath(Long.toString(rawContactId))
-                .build();
-    }
-
-    @Override
-    protected ContactListItemView newView(Context context, int partition, Cursor cursor,
-            int position, ViewGroup parent) {
-        final ContactListItemView view =
-                super.newView(context, partition, cursor, position, parent);
-        view.setUnknownNameText(mUnknownNameText);
-        return view;
-    }
-
-    @Override
-    protected void bindView(View v, int partition, Cursor cursor, int position) {
-        super.bindView(v, partition, cursor, position);
-        final ContactListItemView view = (ContactListItemView) v;
-        bindName(view, cursor);
-        bindViewId(view, cursor, GroupMembersQuery.RAW_CONTACT_ID);
-        bindPhoto(view, cursor);
-    }
-
-    private void bindName(ContactListItemView view, Cursor cursor) {
-        view.showDisplayName(cursor, GroupMembersQuery.CONTACT_DISPLAY_NAME,
-                getContactNameDisplayOrder());
-    }
-
-    private void bindPhoto(final ContactListItemView view, Cursor cursor) {
-        final long photoId = cursor.isNull(GroupMembersQuery.CONTACT_PHOTO_ID)
-                ? 0 : cursor.getLong(GroupMembersQuery.CONTACT_PHOTO_ID);
-        final DefaultImageRequest imageRequest = photoId == 0
-                ? getDefaultImageRequestFromCursor(cursor, GroupMembersQuery.CONTACT_DISPLAY_NAME,
-                GroupMembersQuery.CONTACT_LOOKUP_KEY)
-                : null;
-        getPhotoLoader().loadThumbnail(view.getPhotoView(), photoId, false, getCircularPhotos(),
-                imageRequest);
-    }
-}
diff --git a/src/com/android/contacts/list/GroupMemberPickerFragment.java b/src/com/android/contacts/list/GroupMemberPickerFragment.java
index edd5739..fb378e6 100644
--- a/src/com/android/contacts/list/GroupMemberPickerFragment.java
+++ b/src/com/android/contacts/list/GroupMemberPickerFragment.java
@@ -15,38 +15,29 @@
  */
 package com.android.contacts.list;
 
-import android.app.LoaderManager.LoaderCallbacks;
-import android.content.CursorLoader;
 import android.content.Loader;
 import android.database.Cursor;
 import android.database.CursorWrapper;
-import android.net.Uri;
 import android.os.Bundle;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Data;
 import android.util.Log;
-import android.util.Pair;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
 import com.android.contacts.common.R;
 import com.android.contacts.common.list.ContactEntryListFragment;
+import com.android.contacts.common.list.ContactListAdapter.ContactQuery;
+import com.android.contacts.common.list.ContactListFilter;
+import com.android.contacts.common.list.DefaultContactListAdapter;
 import com.android.contacts.common.model.account.AccountWithDataSet;
-import com.android.contacts.common.preference.ContactsPreferences;
-import com.android.contacts.list.GroupMemberPickListAdapter.GroupMembersQuery;
 
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
 
 /**
  * Fragment containing raw contacts for a specified account that are not already in a group.
  */
 public class GroupMemberPickerFragment extends
-        ContactEntryListFragment<GroupMemberPickListAdapter> {
+        ContactEntryListFragment<DefaultContactListAdapter> {
 
     public static final String TAG = "GroupMemberPicker";
 
@@ -56,13 +47,11 @@
     private static final String ARG_ACCOUNT = "account";
     private static final String ARG_RAW_CONTACT_IDS = "rawContactIds";
 
-    private static final int LOADER_CONTACT_ENTITY = 0;
-
     /** Callbacks for host of {@link GroupMemberPickerFragment}. */
     public interface Listener {
 
         /** Invoked when a potential group member is selected. */
-        void onGroupMemberClicked(Uri uri);
+        void onGroupMemberClicked(long contactId);
     }
 
     /**
@@ -82,23 +71,14 @@
             mIndex = new int[mCount];
 
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "FilterCursorWrapper starting size cursor=" + mCount + " photosMap="
-                        + (mContactPhotosMap == null ? 0 : mContactPhotosMap.size()));
+                Log.v(TAG, "FilterCursorWrapper starting cursor size is " + mCount);
             }
 
-            final Set<String> uniqueRawContactIds = new HashSet<String>();
-
             for (int i = 0; i < mCount; i++) {
                 super.moveToPosition(i);
-                final String rawContactId = getString(GroupMembersQuery.RAW_CONTACT_ID);
-                if (!mRawContactIds.contains(rawContactId)
-                        && !uniqueRawContactIds.contains(rawContactId)) {
+                final String contactId = getString(ContactQuery.CONTACT_ID);
+                if (!mRawContactIds.contains(contactId)) {
                     mIndex[mPos++] = i;
-                    uniqueRawContactIds.add(rawContactId);
-                }
-                if (mRawContactIds.contains(rawContactId) && mContactPhotosMap != null) {
-                    final long contactId = getLong(GroupMembersQuery.CONTACT_ID);
-                    mContactPhotosMap.remove(contactId);
                 }
             }
             mCount = mPos;
@@ -106,82 +86,11 @@
             super.moveToFirst();
 
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "FilterCursorWrapper ending  size cursor=" + mCount + " photosMap="
-                        + (mContactPhotosMap == null ? 0 : mContactPhotosMap.size()));
+                Log.v(TAG, "FilterCursorWrapper ending cursor size is" + mCount);
             }
         }
 
         @Override
-        public int getColumnIndex(String columnName) {
-            final int index = getColumnIndexForContactColumn(columnName);
-            return index < 0 ? super.getColumnIndex(columnName) : index;
-        }
-
-        @Override
-        public int getColumnIndexOrThrow(String columnName) {
-            final int index = getColumnIndexForContactColumn(columnName);
-            return index < 0 ? super.getColumnIndexOrThrow(columnName) : index;
-        }
-
-        private int getColumnIndexForContactColumn(String columnName) {
-            if (Data.PHOTO_ID.equals(columnName)) {
-                return GroupMembersQuery.CONTACT_PHOTO_ID;
-            }
-            if (Data.LOOKUP_KEY.equals(columnName)) {
-                return GroupMembersQuery.CONTACT_LOOKUP_KEY;
-            }
-            return -1;
-        }
-
-        @Override
-        public String[] getColumnNames() {
-            final String displayNameColumnName =
-                    getContactNameDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY
-                            ? Data.DISPLAY_NAME_PRIMARY
-                            : Data.DISPLAY_NAME_ALTERNATIVE;
-            return new String[] {
-                    Data._ID,
-                    Data.CONTACT_ID,
-                    displayNameColumnName,
-                    Data.PHOTO_ID,
-                    Data.LOOKUP_KEY,
-            };
-        }
-
-        @Override
-        public String getString(int columnIndex) {
-            if (columnIndex == GroupMembersQuery.CONTACT_LOOKUP_KEY) {
-                if (columnIndex == GroupMembersQuery.CONTACT_PHOTO_ID) {
-                    final long contactId = getLong(GroupMembersQuery.CONTACT_ID);
-                    final Pair<Long,String> pair = getContactPhotoPair(contactId);
-                    if (pair != null) {
-                        return pair.second;
-                    }
-                }
-                return null;
-            }
-            return super.getString(columnIndex);
-        }
-
-        @Override
-        public long getLong(int columnIndex) {
-            if (columnIndex == GroupMembersQuery.CONTACT_PHOTO_ID) {
-                final long contactId = getLong(GroupMembersQuery.CONTACT_ID);
-                final Pair<Long,String> pair = getContactPhotoPair(contactId);
-                if (pair != null) {
-                    return pair.first;
-                }
-                return 0;
-            }
-            return super.getLong(columnIndex);
-        }
-
-        private Pair<Long,String> getContactPhotoPair(long contactId) {
-            return mContactPhotosMap != null && mContactPhotosMap.containsKey(contactId)
-                ? mContactPhotosMap.get(contactId) : null;
-        }
-
-        @Override
         public boolean move(int offset) {
             return moveToPosition(mPos + offset);
         }
@@ -223,49 +132,15 @@
         }
     }
 
-    private final LoaderCallbacks<Cursor> mContactsEntityCallbacks = new LoaderCallbacks<Cursor>() {
-
-        private final String[] PROJECTION = new String[] {
-                Data.CONTACT_ID,
-                Data.PHOTO_ID,
-                Data.LOOKUP_KEY
-        };
-
-        @Override
-        public CursorLoader onCreateLoader(int id, Bundle args) {
-            final CursorLoader loader = new CursorLoader(getActivity());
-            loader.setUri(Data.CONTENT_URI);
-            loader.setProjection(PROJECTION);
-            return loader;
-        }
-        @Override
-        public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
-            mContactPhotosMap = new HashMap<>();
-            while (cursor.moveToNext()) {
-                final long contactId = cursor.getLong(0);
-                final Pair<Long, String> pair =
-                        new Pair(cursor.getLong(1), cursor.getString(2));
-                mContactPhotosMap.put(contactId, pair);
-            }
-            GroupMemberPickerFragment.super.startLoading();
-        }
-
-        @Override
-        public void onLoaderReset(Loader<Cursor> loader) {}
-    };
-
     private AccountWithDataSet mAccount;
     private ArrayList<String> mRawContactIds;
-    // Contact ID longs to Pairs of photo ID and contact lookup keys
-    private Map<Long, Pair<Long,String>> mContactPhotosMap;
-
     private Listener mListener;
 
     public static GroupMemberPickerFragment newInstance(AccountWithDataSet account,
-            ArrayList<String> rawContactids) {
+            ArrayList<String> rawContactIds) {
         final Bundle args = new Bundle();
         args.putParcelable(ARG_ACCOUNT, account);
-        args.putStringArrayList(ARG_RAW_CONTACT_IDS, rawContactids);
+        args.putStringArrayList(ARG_RAW_CONTACT_IDS, rawContactIds);
 
         final GroupMemberPickerFragment fragment = new GroupMemberPickerFragment();
         fragment.setArguments(args);
@@ -273,15 +148,15 @@
     }
 
     public GroupMemberPickerFragment() {
-        setQuickContactEnabled(false);
         setPhotoLoaderEnabled(true);
+        setSectionHeaderDisplayEnabled(false);
         setVisibleScrollbarEnabled(true);
+
         setHasOptionsMenu(true);
     }
 
     @Override
     public void onCreate(Bundle savedState) {
-        super.onCreate(savedState);
         if (savedState == null) {
             mAccount = getArguments().getParcelable(ARG_ACCOUNT);
             mRawContactIds = getArguments().getStringArrayList(ARG_RAW_CONTACT_IDS);
@@ -289,6 +164,7 @@
             mAccount = savedState.getParcelable(KEY_ACCOUNT);
             mRawContactIds = savedState.getStringArrayList(KEY_RAW_CONTACT_IDS);
         }
+        super.onCreate(savedState);
     }
 
     @Override
@@ -298,15 +174,6 @@
         outState.putStringArrayList(KEY_RAW_CONTACT_IDS, mRawContactIds);
     }
 
-    @Override
-    protected void startLoading() {
-        if (mContactPhotosMap == null) {
-            getLoaderManager().restartLoader(LOADER_CONTACT_ENTITY, null, mContactsEntityCallbacks);
-        } else {
-            super.startLoading();
-        }
-    }
-
     public void setListener(Listener listener) {
         mListener = listener;
     }
@@ -324,24 +191,22 @@
     }
 
     @Override
-    protected GroupMemberPickListAdapter createListAdapter() {
-        final GroupMemberPickListAdapter adapter = new GroupMemberPickListAdapter(getActivity());
+    protected DefaultContactListAdapter createListAdapter() {
+        final DefaultContactListAdapter adapter = new DefaultContactListAdapter(getActivity());
+        adapter.setFilter(ContactListFilter.createGroupMembersFilter(
+                mAccount.type, mAccount.name, mAccount.dataSet));
+        adapter.setSectionHeaderDisplayEnabled(true);
         adapter.setDisplayPhotos(true);
         return adapter;
     }
 
     @Override
-    protected void configureAdapter() {
-        super.configureAdapter();
-        getAdapter().setAccount(mAccount);
-        getAdapter().setRawContactIds(mRawContactIds);
-        getAdapter().setEmptyListEnabled(true);
-    }
-
-    @Override
     protected void onItemClick(int position, long id) {
         if (mListener != null) {
-            mListener.onGroupMemberClicked(getAdapter().getRawContactUri(position));
+            final long contactId = getAdapter().getContactId(position);
+            if (contactId > 0) {
+                mListener.onGroupMemberClicked(contactId);
+            }
         }
     }
 }
diff --git a/src/com/android/contacts/list/GroupMemberTileAdapter.java b/src/com/android/contacts/list/GroupMemberTileAdapter.java
deleted file mode 100644
index 15e67f1..0000000
--- a/src/com/android/contacts/list/GroupMemberTileAdapter.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2012 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.list;
-
-import android.content.Context;
-import android.database.Cursor;
-
-import com.android.contacts.GroupMemberLoader;
-import com.android.contacts.common.list.ContactEntry;
-import com.android.contacts.common.list.ContactTileAdapter;
-import com.android.contacts.common.list.ContactTileView;
-import com.google.common.collect.Lists;
-
-import java.util.ArrayList;
-
-/**
- * Tile adapter for groups.
- */
-public class GroupMemberTileAdapter extends ContactTileAdapter {
-
-    public GroupMemberTileAdapter(Context context, ContactTileView.Listener listener, int numCols) {
-        super(context, listener, numCols, DisplayType.GROUP_MEMBERS);
-    }
-
-    @Override
-    protected void bindColumnIndices() {
-        mIdIndex = GroupMemberLoader.GroupDetailQuery.CONTACT_ID;
-        mLookupIndex = GroupMemberLoader.GroupDetailQuery.CONTACT_LOOKUP_KEY;
-        mPhotoUriIndex = GroupMemberLoader.GroupDetailQuery.CONTACT_PHOTO_URI;
-        mNameIndex = GroupMemberLoader.GroupDetailQuery.CONTACT_DISPLAY_NAME_PRIMARY;
-        mPresenceIndex = GroupMemberLoader.GroupDetailQuery.CONTACT_PRESENCE_STATUS;
-        mStatusIndex = GroupMemberLoader.GroupDetailQuery.CONTACT_STATUS;
-    }
-
-    @Override
-    protected void saveNumFrequentsFromCursor(Cursor cursor) {
-        mNumFrequents = 0;
-    }
-
-    @Override
-    public int getItemViewType(int position) {
-        return ViewTypes.STARRED;
-    }
-
-    @Override
-    protected int getDividerPosition(Cursor cursor) {
-        // No divider
-        return -1;
-    }
-
-    @Override
-    public int getCount() {
-        if (mContactCursor == null || mContactCursor.isClosed()) {
-            return 0;
-        }
-
-        return getRowCount(mContactCursor.getCount());
-    }
-
-    @Override
-    public ArrayList<ContactEntry> getItem(int position) {
-        final ArrayList<ContactEntry> resultList = Lists.newArrayListWithCapacity(mColumnCount);
-        int contactIndex = position * mColumnCount;
-
-        for (int columnCounter = 0; columnCounter < mColumnCount; columnCounter++) {
-            resultList.add(createContactEntryFromCursor(mContactCursor, contactIndex));
-            contactIndex++;
-        }
-        return resultList;
-    }
-}
diff --git a/src/com/android/contacts/list/UiIntentActions.java b/src/com/android/contacts/list/UiIntentActions.java
index 31e5ade..571d56f 100644
--- a/src/com/android/contacts/list/UiIntentActions.java
+++ b/src/com/android/contacts/list/UiIntentActions.java
@@ -40,16 +40,16 @@
     public static final String GROUP_NAME_EXTRA_KEY = "com.android.contacts.extra.GROUP";
 
     /**
-     * The account used to filter potential raw contact groups members.
+     * The account used to filter potential new group members.
      */
     public static final String GROUP_ACCOUNT_WITH_DATA_SET =
             "com.android.contacts.extra.GROUP_ACCOUNT_WITH_DATA_SET";
 
     /**
-     * The raw contact IDs for existing group members.
+     * The contact IDs for existing group members.
      */
-    public static final String GROUP_RAW_CONTACT_IDS =
-            "com.android.contacts.extra.GROUP_RAW_CONTACT_IDS";
+    public static final String GROUP_CONTACT_IDS =
+            "com.android.contacts.extra.GROUP_CONTACT_IDS";
 
     /**
      * The action for the all contacts list tab.
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 76e8605..64db298 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -209,6 +209,9 @@
 
     /** Used to pass the screen where the user came before launching this Activity. */
     public static final String EXTRA_PREVIOUS_SCREEN_TYPE = "previous_screen_type";
+    /** Used to tell the QuickContact that the previous contact was edited, so it can return an
+     * activity result back to the original Activity that launched it. */
+    public static final String EXTRA_CONTACT_EDITED = "contact_edited";
 
     private static final String TAG = "QuickContact";
 
@@ -1209,6 +1212,9 @@
             return;
         }
         Uri lookupUri = intent.getData();
+        if (intent.getBooleanExtra(EXTRA_CONTACT_EDITED, false)) {
+            setResult(ContactEditorBaseActivity.RESULT_CODE_EDITED);
+        }
 
         // Check to see whether it comes from the old version.
         if (lookupUri != null && LEGACY_AUTHORITY.equals(lookupUri.getAuthority())) {