Update group editor styles and avatars for dogfood

* Use standard action bar w/ done button placement
  matching that on the contact editor
* Replace group member QuickContactBadge avatar with
  letter tile to match avatars in the main contacts
  lists. Also put it on the left side.
* Make the name in each group member row clickable.
* Don't use a two panel screen in landscape any more.

Bug 18641067

Change-Id: Id45a6ceb0a138906078356fa71a72225add07ecf
diff --git a/res/layout-land/group_editor_view.xml b/res/layout-land/group_editor_view.xml
deleted file mode 100644
index dded4c3..0000000
--- a/res/layout-land/group_editor_view.xml
+++ /dev/null
@@ -1,63 +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.
--->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical" >
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:paddingLeft="8dip"
-        android:paddingRight="8dip"
-        android:paddingStart="8dip"
-        android:paddingEnd="8dip"
-        android:orientation="horizontal"
-        >
-
-        <EditText
-            android:id="@+id/group_name"
-            android:layout_width="0dip"
-            android:layout_weight="1"
-            android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:inputType="textCapWords"
-            android:imeOptions="flagNoExtractUi|flagNoFullscreen"
-            android:hint="@string/group_name_hint"
-            android:minHeight="48dip"
-            android:paddingRight="8dip"
-            android:paddingEnd="8dip"
-            />
-
-        <LinearLayout
-            android:layout_width="0dip"
-            android:layout_weight="1"
-            android:layout_height="match_parent"
-            android:paddingLeft="8dip"
-            android:paddingStart="8dip"
-            android:orientation="vertical"
-            >
-            <include
-                layout="@layout/group_editor_autocomplete_view"
-                android:id="@+id/add_member_field"/>
-            <include
-                layout="@layout/group_editor_existing_member_list"
-                android:id="@android:id/list"/>
-        </LinearLayout>
-    </LinearLayout>
-</LinearLayout>
diff --git a/res/layout-sw600dp/external_group_editor_view.xml b/res/layout-sw600dp/external_group_editor_view.xml
deleted file mode 100644
index 9702bc7..0000000
--- a/res/layout-sw600dp/external_group_editor_view.xml
+++ /dev/null
@@ -1,72 +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.
--->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:paddingTop="50dip"
-    android:paddingLeft="50dip"
-    android:paddingRight="100dip"
-    android:paddingStart="50dip"
-    android:paddingEnd="100dip"
-    android:orientation="horizontal"
-    android:background="@color/background_primary">
-
-    <LinearLayout
-        android:layout_width="0dip"
-        android:layout_height="match_parent"
-        android:layout_weight="3"
-        android:layout_marginRight="30dip"
-        android:layout_marginEnd="30dip"
-        android:orientation="vertical">
-
-        <TextView
-            android:id="@+id/read_only_warning"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingTop="10dip"
-            android:paddingLeft="10dip"
-            android:paddingRight="10dip"
-            android:paddingStart="10dip"
-            android:paddingEnd="10dip"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorTertiary"
-            android:text="@string/group_read_only" />
-
-        <include
-            android:id="@+id/account_header"
-            layout="@layout/editor_account_header"/>
-
-        <TextView
-            android:id="@+id/group_name"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textColor="?android:attr/textColorTertiary"
-            android:textStyle="bold"
-            android:padding="10dip"/>
-
-    </LinearLayout>
-
-    <include
-        layout="@layout/group_editor_existing_member_list"
-        android:id="@android:id/list"
-        android:layout_width="0dip"
-        android:layout_height="match_parent"
-        android:layout_weight="2"/>
-
-</LinearLayout>
diff --git a/res/layout-sw600dp/group_editor_view.xml b/res/layout-sw600dp/group_editor_view.xml
deleted file mode 100644
index 717fc28..0000000
--- a/res/layout-sw600dp/group_editor_view.xml
+++ /dev/null
@@ -1,76 +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.
--->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:paddingTop="32dip"
-    android:paddingLeft="@dimen/group_editor_side_padding"
-    android:paddingRight="@dimen/group_editor_side_padding"
-    android:paddingStart="@dimen/group_editor_side_padding"
-    android:paddingEnd="@dimen/group_editor_side_padding"
-    android:orientation="horizontal"
-    android:background="@color/background_primary">
-
-    <LinearLayout
-        android:layout_width="0dip"
-        android:layout_height="match_parent"
-        android:layout_weight="3"
-        android:layout_marginRight="30dip"
-        android:layout_marginEnd="30dip"
-        android:orientation="vertical">
-
-        <include
-            android:id="@+id/account_header"
-            layout="@layout/editor_account_header"/>
-
-        <EditText
-            android:id="@+id/group_name"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:minHeight="48dip"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:inputType="textCapWords"
-            android:hint="@string/group_name_hint"
-            android:paddingLeft="16dip"
-            android:paddingStart="16dip"/>
-
-    </LinearLayout>
-
-    <LinearLayout
-        android:id="@+id/group_members"
-        android:layout_width="0dip"
-        android:layout_height="match_parent"
-        android:layout_weight="2"
-        android:orientation="vertical">
-
-        <include
-            android:id="@+id/spacer"
-            layout="@layout/editor_account_header"
-            android:visibility="invisible"/>
-
-        <include
-            layout="@layout/group_editor_autocomplete_view"
-            android:id="@+id/add_member_field"/>
-
-        <include
-            layout="@layout/group_editor_existing_member_list"
-            android:id="@android:id/list"/>
-
-    </LinearLayout>
-
-</LinearLayout>
diff --git a/res/layout/external_group_member_item.xml b/res/layout/external_group_member_item.xml
index a56d91d..3be9979 100644
--- a/res/layout/external_group_member_item.xml
+++ b/res/layout/external_group_member_item.xml
@@ -20,6 +20,16 @@
     android:layout_height="wrap_content"
     android:orientation="horizontal">
 
+    <ImageView
+        android:id="@+id/photo"
+        android:layout_marginLeft="5dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginStart="5dip"
+        android:layout_marginEnd="10dip"
+        android:layout_gravity="center_vertical"
+        android:layout_width="50dip"
+        android:layout_height="50dip" />
+
     <TextView
         android:id="@+id/name"
         android:layout_height="wrap_content"
@@ -34,15 +44,4 @@
         android:paddingLeft="@dimen/group_member_item_left_padding"
         android:paddingStart="@dimen/group_member_item_left_padding" />
 
-    <QuickContactBadge
-        android:id="@+id/badge"
-        android:layout_marginLeft="5dip"
-        android:layout_marginRight="10dip"
-        android:layout_marginStart="5dip"
-        android:layout_marginEnd="10dip"
-        android:layout_gravity="center_vertical"
-        android:layout_width="50dip"
-        android:layout_height="50dip"
-        style="?android:attr/quickContactBadgeStyleWindowMedium" />
-
 </LinearLayout>
diff --git a/res/layout/group_member_item.xml b/res/layout/group_member_item.xml
index 14ed833..11ab621 100644
--- a/res/layout/group_member_item.xml
+++ b/res/layout/group_member_item.xml
@@ -20,6 +20,16 @@
     android:layout_height="wrap_content"
     android:orientation="horizontal">
 
+    <ImageView
+        android:id="@+id/photo"
+        android:layout_marginLeft="5dip"
+        android:layout_marginRight="10dip"
+        android:layout_marginStart="5dip"
+        android:layout_marginEnd="10dip"
+        android:layout_gravity="center_vertical"
+        android:layout_width="50dip"
+        android:layout_height="50dip"/>
+
     <TextView
         android:id="@+id/name"
         android:layout_height="wrap_content"
@@ -34,17 +44,6 @@
         android:paddingLeft="@dimen/group_member_item_left_padding"
         android:paddingStart="@dimen/group_member_item_left_padding" />
 
-    <QuickContactBadge
-        android:id="@+id/badge"
-        android:layout_marginLeft="5dip"
-        android:layout_marginRight="10dip"
-        android:layout_marginStart="5dip"
-        android:layout_marginEnd="10dip"
-        android:layout_gravity="center_vertical"
-        android:layout_width="50dip"
-        android:layout_height="50dip"
-        style="?android:attr/quickContactBadgeStyleWindowMedium" />
-
     <include
         android:id="@+id/delete_button_container"
         layout="@layout/edit_delete_button"
diff --git a/res/menu/edit_group.xml b/res/menu/edit_group.xml
index a3387ca..b94563f 100644
--- a/res/menu/edit_group.xml
+++ b/res/menu/edit_group.xml
@@ -16,6 +16,11 @@
 
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
     <item
+        android:id="@+id/menu_save"
+        android:showAsAction="always"
+        android:icon="@drawable/ic_done_wht_24dp"
+        android:title="@string/menu_save" />
+    <item
         android:id="@+id/menu_discard"
         android:alphabeticShortcut="q"
         android:title="@string/menu_discard"
diff --git a/src/com/android/contacts/GroupMemberLoader.java b/src/com/android/contacts/GroupMemberLoader.java
index 6001f2c..43a6427 100644
--- a/src/com/android/contacts/GroupMemberLoader.java
+++ b/src/com/android/contacts/GroupMemberLoader.java
@@ -41,6 +41,7 @@
             Data.DISPLAY_NAME_PRIMARY,              // 2
             Data.PHOTO_URI,                         // 3
             Data.LOOKUP_KEY,                        // 4
+            Data.PHOTO_ID,                          // 5
         };
 
         public static final int CONTACT_ID                   = 0;
@@ -48,6 +49,7 @@
         public static final int CONTACT_DISPLAY_NAME_PRIMARY = 2;
         public static final int CONTACT_PHOTO_URI            = 3;
         public static final int CONTACT_LOOKUP_KEY           = 4;
+        public static final int CONTACT_PHOTO_ID             = 5;
     }
 
     public static class GroupDetailQuery {
diff --git a/src/com/android/contacts/activities/GroupEditorActivity.java b/src/com/android/contacts/activities/GroupEditorActivity.java
index d48ed97..8a285a7 100644
--- a/src/com/android/contacts/activities/GroupEditorActivity.java
+++ b/src/com/android/contacts/activities/GroupEditorActivity.java
@@ -18,20 +18,17 @@
 
 import android.app.ActionBar;
 import android.app.Dialog;
-import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
 import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
 
 import com.android.contacts.ContactsActivity;
 import com.android.contacts.R;
+import com.android.contacts.common.util.ImplicitIntentsUtil;
 import com.android.contacts.group.GroupEditorFragment;
+import com.android.contacts.quickcontact.QuickContactActivity;
 import com.android.contacts.util.DialogManager;
-import com.android.contacts.util.PhoneCapabilityTester;
 
 public class GroupEditorActivity extends ContactsActivity
         implements DialogManager.DialogShowingViewActivity {
@@ -39,8 +36,6 @@
     private static final String TAG = "GroupEditorActivity";
 
     public static final String ACTION_SAVE_COMPLETED = "saveCompleted";
-    public static final String ACTION_ADD_MEMBER_COMPLETED = "addMemberCompleted";
-    public static final String ACTION_REMOVE_MEMBER_COMPLETED = "removeMemberCompleted";
 
     private GroupEditorFragment mFragment;
 
@@ -60,24 +55,9 @@
 
         ActionBar actionBar = getActionBar();
         if (actionBar != null) {
-            // Inflate a custom action bar that contains the "done" button for saving changes
-            // to the group
-            LayoutInflater inflater = (LayoutInflater) getSystemService
-                    (Context.LAYOUT_INFLATER_SERVICE);
-            View customActionBarView = inflater.inflate(R.layout.editor_custom_action_bar,
-                    null);
-            View saveMenuItem = customActionBarView.findViewById(R.id.save_menu_item);
-            saveMenuItem.setOnClickListener(new OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    mFragment.onDoneClicked();
-                }
-            });
-            // Show the custom action bar but hide the home icon and title
-            actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
-                    ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME |
-                    ActionBar.DISPLAY_SHOW_TITLE);
-            actionBar.setCustomView(customActionBarView);
+            actionBar.setTitle(getResources().getString(R.string.editGroupDescription));
+            actionBar.setDisplayShowHomeEnabled(true);
+            actionBar.setDisplayHomeAsUpEnabled(true);
         }
 
         mFragment = (GroupEditorFragment) getFragmentManager().findFragmentById(
@@ -153,6 +133,12 @@
                 finish();
             }
         }
+
+        @Override
+        public void onGroupMemberClicked(Uri contactLookupUri) {
+            startActivity(ImplicitIntentsUtil.composeQuickContactIntent(
+                    contactLookupUri, QuickContactActivity.MODE_FULLY_EXPANDED));
+        }
     };
 
     @Override
diff --git a/src/com/android/contacts/group/GroupEditorFragment.java b/src/com/android/contacts/group/GroupEditorFragment.java
index 1104c02..25a07f1 100644
--- a/src/com/android/contacts/group/GroupEditorFragment.java
+++ b/src/com/android/contacts/group/GroupEditorFragment.java
@@ -53,7 +53,6 @@
 import android.widget.BaseAdapter;
 import android.widget.ImageView;
 import android.widget.ListView;
-import android.widget.QuickContactBadge;
 import android.widget.TextView;
 import android.widget.Toast;
 
@@ -71,7 +70,6 @@
 import com.android.contacts.group.SuggestedMemberListAdapter.SuggestedMember;
 import com.android.contacts.common.model.AccountTypeManager;
 import com.android.contacts.common.util.AccountsListAdapter.AccountListFilter;
-import com.android.contacts.common.util.ViewUtil;
 
 import com.google.common.base.Objects;
 
@@ -118,6 +116,11 @@
          * Fragment is created but there's no accounts set up.
          */
         void onAccountsNotFound();
+
+        /**
+         * Group member name or photo was clicked in order to view contact details.
+         */
+        void onGroupMemberClicked(Uri contactLookupUri);
     }
 
     private static final int LOADER_GROUP_METADATA = 1;
@@ -514,6 +517,23 @@
         inflater.inflate(R.menu.edit_group, menu);
     }
 
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case android.R.id.home: {
+                getActivity().onBackPressed();
+                return true;
+            }
+            case R.id.menu_save:
+                onDoneClicked();
+                return true;
+            case R.id.menu_discard:
+                doRevertAction();
+                return true;
+        }
+        return false;
+    }
+
     private void doRevertAction() {
         // When this Fragment is closed we don't want it to auto-save
         mStatus = Status.CLOSING;
@@ -768,8 +788,9 @@
                 String lookupKey = data.getString(GroupEditorQuery.CONTACT_LOOKUP_KEY);
                 String displayName = data.getString(GroupEditorQuery.CONTACT_DISPLAY_NAME_PRIMARY);
                 String photoUri = data.getString(GroupEditorQuery.CONTACT_PHOTO_URI);
+                long photoId = data.getLong(GroupEditorQuery.CONTACT_PHOTO_ID);
                 listExistingMembers.add(new Member(rawContactId, lookupKey, contactId,
-                        displayName, photoUri));
+                        displayName, photoUri, photoId));
             }
 
             // Update the display list
@@ -813,8 +834,10 @@
             String displayName = cursor.getString(CONTACT_DISPLAY_NAME_PRIMARY_COLUMN_INDEX);
             String lookupKey = cursor.getString(CONTACT_LOOKUP_KEY_COLUMN_INDEX);
             String photoUri = cursor.getString(CONTACT_PHOTO_URI_COLUMN_INDEX);
+            long photoId = cursor.getLong(CONTACT_PHOTO_ID_COLUMN_INDEX);
             getLoaderManager().destroyLoader(LOADER_NEW_GROUP_MEMBER);
-            Member member = new Member(mRawContactId, lookupKey, contactId, displayName, photoUri);
+            Member member = new Member(mRawContactId, lookupKey, contactId, displayName, photoUri,
+                    photoId);
             addMember(member);
         }
 
@@ -834,15 +857,17 @@
         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) {
+                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() {
@@ -869,6 +894,10 @@
             return mPhotoUri;
         }
 
+        public long getPhotoId() {
+            return mPhotoId;
+        }
+
         @Override
         public boolean equals(Object object) {
             if (object instanceof Member) {
@@ -897,6 +926,7 @@
             dest.writeString(mLookupKey);
             dest.writeString(mDisplayName);
             dest.writeParcelable(mPhotoUri, flags);
+            dest.writeLong(mPhotoId);
         }
 
         private Member(Parcel in) {
@@ -906,6 +936,7 @@
             mLookupKey = in.readString();
             mDisplayName = in.readString();
             mPhotoUri = in.readParcelable(getClass().getClassLoader());
+            mPhotoId = in.readLong();
         }
 
         public static final Parcelable.Creator<Member> CREATOR = new Parcelable.Creator<Member>() {
@@ -939,12 +970,18 @@
                 result = convertView;
             }
             final Member member = getItem(position);
-
-            QuickContactBadge badge = (QuickContactBadge) result.findViewById(R.id.badge);
-            badge.assignContactUri(member.getLookupUri());
+            final OnClickListener groupMemberClickListener = new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    if (mListener != null) {
+                        mListener.onGroupMemberClicked(member.getLookupUri());
+                    }
+                }
+            };
 
             TextView name = (TextView) result.findViewById(R.id.name);
             name.setText(member.getDisplayName());
+            name.setOnClickListener(groupMemberClickListener);
 
             View deleteButton = result.findViewById(R.id.delete_button_container);
             if (deleteButton != null) {
@@ -955,11 +992,13 @@
                     }
                 });
             }
-            DefaultImageRequest request = new DefaultImageRequest(member.getDisplayName(),
-                    member.getLookupKey(), true /* isCircular */);
-            mPhotoManager.loadPhoto(badge, member.getPhotoUri(),
-                    ViewUtil.getConstantPreLayoutWidth(badge), false, true /* isCircular */,
-                            request);
+
+            // Bind photo
+            final ImageView imageView = (ImageView) result.findViewById(R.id.photo);
+            imageView.setOnClickListener(groupMemberClickListener);
+            bindPhoto(mPhotoManager, imageView, member.getPhotoId(), member.getPhotoUri(),
+                    member.getDisplayName(), member.getLookupKey());
+
             return result;
         }
 
@@ -982,4 +1021,23 @@
             mIsGroupMembershipEditable = editable;
         }
     }
+
+    /**
+     * @param identifier the {@link ContactPhotoManager.DefaultImageRequest#identifier}
+     *         to use for this the group member.
+     */
+    public static void bindPhoto(ContactPhotoManager photoManager, ImageView imageView,
+            long photoId, Uri photoUri, String displayName, String identifier) {
+        if (photoId == 0) {
+            final DefaultImageRequest defaultImageRequest = photoUri == null
+                    ? new DefaultImageRequest(displayName, identifier,
+                            /* circularPhotos */ true)
+                    : null;
+            photoManager.loadDirectoryPhoto(imageView, photoUri, /* darkTheme */ false,
+                        /* isCircular */ true, defaultImageRequest);
+        } else {
+            photoManager.loadThumbnail(imageView, photoId, /* darkTheme */ false,
+                        /* isCircular */ true, /* defaultImageRequest */ null);
+        }
+    }
 }
diff --git a/src/com/android/contacts/group/SuggestedMemberListAdapter.java b/src/com/android/contacts/group/SuggestedMemberListAdapter.java
index 19ff611..eb80ac4 100644
--- a/src/com/android/contacts/group/SuggestedMemberListAdapter.java
+++ b/src/com/android/contacts/group/SuggestedMemberListAdapter.java
@@ -16,10 +16,17 @@
 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;
@@ -69,6 +76,7 @@
         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;
@@ -76,6 +84,7 @@
     private Filter mFilter;
     private ContentResolver mContentResolver;
     private LayoutInflater mInflater;
+    private ContactPhotoManager mPhotoManager;
 
     private String mAccountType;
     private String mAccountName;
@@ -90,6 +99,7 @@
     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) {
@@ -144,16 +154,56 @@
         }
         byte[] byteArray = member.getPhotoByteArray();
         if (byteArray == null) {
-            icon.setImageDrawable(ContactPhotoManager.getDefaultAvatarDrawableForContact(
-                    icon.getResources(), false, null));
+            final Uri contactLookupUri = RawContacts.getContactLookupUri(mContentResolver,
+                    ContentUris.withAppendedId(RawContacts.CONTENT_URI, member.getContactId()));
+            final String imageRequestIdentifier = contactLookupUri == null
+                    ? null : contactLookupUri.toString();
+            GroupEditorFragment.bindPhoto(mPhotoManager, icon, member.getPhotoId(),
+                /* photoUri */ null, member.getDisplayName(), imageRequestIdentifier);
         } else {
             Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
-            icon.setImageBitmap(bitmap);
+            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) {
@@ -277,6 +327,7 @@
                         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) ||
@@ -327,8 +378,10 @@
         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;
@@ -356,6 +409,10 @@
             return mPhoto;
         }
 
+        public long getPhotoId() {
+            return mPhotoId;
+        }
+
         public boolean hasExtraInfo() {
             return mExtraInfo != null;
         }
@@ -371,6 +428,10 @@
             mPhoto = photo;
         }
 
+        public void setPhotoId(long photoId) {
+            mPhotoId = photoId;
+        }
+
         @Override
         public String toString() {
             return getDisplayName();