Add circular photo support to ContactPhotoManager

* Use RoundedBitmapDrawable to draw circular bitmaps

* Add isCircular to DefaultImageRequest, and add circular
support to LetterTileDrawable

* Temporarily disable fading in contact photos using
TransitionImageDrawable

Bug: 13747208

Change-Id: I4d087b2dab701014297912ccb6cfac36ecffc673
diff --git a/TestCommon/src/com/android/contacts/common/test/mocks/MockContactPhotoManager.java b/TestCommon/src/com/android/contacts/common/test/mocks/MockContactPhotoManager.java
index dd919cc..98b771c 100644
--- a/TestCommon/src/com/android/contacts/common/test/mocks/MockContactPhotoManager.java
+++ b/TestCommon/src/com/android/contacts/common/test/mocks/MockContactPhotoManager.java
@@ -28,14 +28,15 @@
  */
 public class MockContactPhotoManager extends ContactPhotoManager {
     @Override
-    public void loadThumbnail(ImageView view, long photoId, boolean darkTheme,
+    public void loadThumbnail(ImageView view, long photoId, boolean darkTheme, boolean isCircular,
             DefaultImageRequest defaultImageRequest, DefaultImageProvider defaultProvider) {
         defaultProvider.applyDefaultImage(view, -1, darkTheme, null);
     }
 
     @Override
     public void loadPhoto(ImageView view, Uri photoUri, int requestedExtent, boolean darkTheme,
-            DefaultImageRequest defaultImageRequest, DefaultImageProvider defaultProvider) {
+            boolean isCircular, DefaultImageRequest defaultImageRequest,
+            DefaultImageProvider defaultProvider) {
         defaultProvider.applyDefaultImage(view, requestedExtent, darkTheme, null);
     }
 
diff --git a/src/com/android/contacts/common/ContactPhotoManager.java b/src/com/android/contacts/common/ContactPhotoManager.java
index f3a73ff..716c947 100644
--- a/src/com/android/contacts/common/ContactPhotoManager.java
+++ b/src/com/android/contacts/common/ContactPhotoManager.java
@@ -44,6 +44,7 @@
 import android.provider.ContactsContract.Contacts.Photo;
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.Directory;
+import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.LruCache;
@@ -86,12 +87,15 @@
     public static final float SCALE_DEFAULT = 1.0f;
     public static final float OFFSET_DEFAULT = 0.0f;
 
+    public static final boolean IS_CIRCULAR_DEFAULT = false;
+
     /** Uri-related constants used for default letter images */
     private static final String DISPLAY_NAME_PARAM_KEY = "display_name";
     private static final String IDENTIFIER_PARAM_KEY = "identifier";
     private static final String CONTACT_TYPE_PARAM_KEY = "contact_type";
     private static final String SCALE_PARAM_KEY = "scale";
     private static final String OFFSET_PARAM_KEY = "offset";
+    private static final String IS_CIRCULAR_PARAM_KEY = "is_circular";
     private static final String DEFAULT_IMAGE_URI_SCHEME = "defaultimage";
     private static final Uri DEFAULT_IMAGE_URI = Uri.parse(DEFAULT_IMAGE_URI_SCHEME + "://");
 
@@ -153,6 +157,10 @@
             if (request.offset != OFFSET_DEFAULT) {
                 builder.appendQueryParameter(OFFSET_PARAM_KEY, String.valueOf(request.offset));
             }
+            if (request.isCircular != IS_CIRCULAR_DEFAULT) {
+                builder.appendQueryParameter(IS_CIRCULAR_PARAM_KEY,
+                        String.valueOf(request.isCircular));
+            }
 
         }
         return builder.build();
@@ -161,7 +169,7 @@
     protected static DefaultImageRequest getDefaultImageRequestFromUri(Uri uri) {
         final DefaultImageRequest request = new DefaultImageRequest(
                 uri.getQueryParameter(DISPLAY_NAME_PARAM_KEY),
-                uri.getQueryParameter(IDENTIFIER_PARAM_KEY));
+                uri.getQueryParameter(IDENTIFIER_PARAM_KEY), false);
         try {
             String contactType = uri.getQueryParameter(CONTACT_TYPE_PARAM_KEY);
             if (!TextUtils.isEmpty(contactType)) {
@@ -177,6 +185,11 @@
             if (!TextUtils.isEmpty(offset)) {
                 request.offset = Float.valueOf(offset);
             }
+
+            String isCircular = uri.getQueryParameter(IS_CIRCULAR_PARAM_KEY);
+            if (!TextUtils.isEmpty(isCircular)) {
+                request.isCircular = Boolean.valueOf(isCircular);
+            }
         } catch (NumberFormatException e) {
             Log.w(TAG, "Invalid DefaultImageRequest image parameters provided, ignoring and using "
                     + "defaults.");
@@ -199,6 +212,7 @@
          * The contact's display name. The display name is used to
          */
         public String displayName;
+
         /**
          * A unique and deterministic string that can be used to identify this contact. This is
          * usually the contact's lookup key, but other contact details can be used as well,
@@ -206,6 +220,7 @@
          * is used to determine the color of the tile.
          */
         public String identifier;
+
         /**
          * The type of this contact. This contact type may be used to decide the kind of
          * image to use in the case where a unique letter cannot be generated from the contact's
@@ -216,11 +231,13 @@
          * {@link #TYPE_DEFAULT}
          */
         public int contactType = TYPE_DEFAULT;
+
         /**
          * The amount to scale the letter or bitmap to, as a ratio of its default size (from a
          * range of 0.0f to 2.0f). The default value is 1.0f.
          */
         public float scale = SCALE_DEFAULT;
+
         /**
          * The amount to vertically offset the letter or image to within the tile.
          * The provided offset must be within the range of -0.5f to 0.5f.
@@ -235,24 +252,44 @@
          */
         public float offset = OFFSET_DEFAULT;
 
+        /**
+         * Whether or not to draw the default image as a circle, instead of as a square/rectangle.
+         */
+        public boolean isCircular = false;
+
+        /**
+         * Used to indicate that a drawable that represents a contact without any contact details
+         * should be returned.
+         */
+        public static DefaultImageRequest EMPTY_DEFAULT_IMAGE_REQUEST = new DefaultImageRequest();
+
+        /**
+         * Used to indicate that a circular drawable that represents a contact without any contact
+         * details should be returned.
+         */
+        public static DefaultImageRequest EMPTY_CIRCULAR_DEFAULT_IMAGE_REQUEST =
+                new DefaultImageRequest(null, null, true);
+
         public DefaultImageRequest() {
         }
 
-        public DefaultImageRequest(String displayName, String identifier) {
-            this(displayName, identifier, TYPE_DEFAULT, SCALE_DEFAULT, OFFSET_DEFAULT);
-        }
-
-        public DefaultImageRequest(String displayName, String identifier, int contactType) {
-            this(displayName, identifier, contactType, SCALE_DEFAULT, OFFSET_DEFAULT);
+        public DefaultImageRequest(String displayName, String identifier, boolean isCircular) {
+            this(displayName, identifier, TYPE_DEFAULT, SCALE_DEFAULT, OFFSET_DEFAULT, isCircular);
         }
 
         public DefaultImageRequest(String displayName, String identifier, int contactType,
-                float scale, float offset) {
+                boolean isCircular) {
+            this(displayName, identifier, contactType, SCALE_DEFAULT, OFFSET_DEFAULT, isCircular);
+        }
+
+        public DefaultImageRequest(String displayName, String identifier, int contactType,
+                float scale, float offset, boolean isCircular) {
             this.displayName = displayName;
             this.identifier = identifier;
             this.contactType = contactType;
             this.scale = scale;
             this.offset = offset;
+            this.isCircular = isCircular;
         }
     }
 
@@ -299,6 +336,7 @@
                 drawable.setContactType(defaultImageRequest.contactType);
                 drawable.setScale(defaultImageRequest.scale);
                 drawable.setOffset(defaultImageRequest.offset);
+                drawable.setIsCircular(defaultImageRequest.isCircular);
             }
             return drawable;
         }
@@ -344,15 +382,16 @@
      * from the database.
      */
     public abstract void loadThumbnail(ImageView view, long photoId, boolean darkTheme,
-            DefaultImageRequest defaultImageRequest, DefaultImageProvider defaultProvider);
+            boolean isCircular, DefaultImageRequest defaultImageRequest,
+            DefaultImageProvider defaultProvider);
 
     /**
      * Calls {@link #loadThumbnail(ImageView, long, boolean, DefaultImageRequest,
      * DefaultImageProvider)} using the {@link DefaultImageProvider} {@link #DEFAULT_AVATAR}.
     */
     public final void loadThumbnail(ImageView view, long photoId, boolean darkTheme,
-            DefaultImageRequest defaultImageRequest) {
-        loadThumbnail(view, photoId, darkTheme, defaultImageRequest, DEFAULT_AVATAR);
+            boolean isCircular, DefaultImageRequest defaultImageRequest) {
+        loadThumbnail(view, photoId, darkTheme, isCircular, defaultImageRequest, DEFAULT_AVATAR);
     }
 
 
@@ -374,7 +413,7 @@
      * refer to an existing image)
      */
     public abstract void loadPhoto(ImageView view, Uri photoUri, int requestedExtent,
-            boolean darkTheme, DefaultImageRequest defaultImageRequest,
+            boolean darkTheme, boolean isCircular, DefaultImageRequest defaultImageRequest,
             DefaultImageProvider defaultProvider);
 
     /**
@@ -386,8 +425,9 @@
      * letter tile avatar should be drawn.
      */
     public final void loadPhoto(ImageView view, Uri photoUri, int requestedExtent,
-            boolean darkTheme, DefaultImageRequest defaultImageRequest) {
-        loadPhoto(view, photoUri, requestedExtent, darkTheme, defaultImageRequest, DEFAULT_AVATAR);
+            boolean darkTheme, boolean isCircular, DefaultImageRequest defaultImageRequest) {
+        loadPhoto(view, photoUri, requestedExtent, darkTheme, isCircular,
+                defaultImageRequest, DEFAULT_AVATAR);
     }
 
     /**
@@ -399,8 +439,8 @@
      * letter tile avatar should be drawn.
      */
     public final void loadDirectoryPhoto(ImageView view, Uri photoUri, boolean darkTheme,
-            DefaultImageRequest defaultImageRequest) {
-        loadPhoto(view, photoUri, -1, darkTheme, defaultImageRequest, DEFAULT_AVATAR);
+            boolean isCircular, DefaultImageRequest defaultImageRequest) {
+        loadPhoto(view, photoUri, -1, darkTheme, isCircular, defaultImageRequest, DEFAULT_AVATAR);
     }
 
     /**
@@ -674,7 +714,7 @@
     }
 
     @Override
-    public void loadThumbnail(ImageView view, long photoId, boolean darkTheme,
+    public void loadThumbnail(ImageView view, long photoId, boolean darkTheme, boolean isCircular,
             DefaultImageRequest defaultImageRequest, DefaultImageProvider defaultProvider) {
         if (photoId == 0) {
             // No photo is needed
@@ -682,14 +722,15 @@
             mPendingRequests.remove(view);
         } else {
             if (DEBUG) Log.d(TAG, "loadPhoto request: " + photoId);
-            loadPhotoByIdOrUri(view, Request.createFromThumbnailId(photoId, darkTheme,
+            loadPhotoByIdOrUri(view, Request.createFromThumbnailId(photoId, darkTheme, isCircular,
                     defaultProvider));
         }
     }
 
     @Override
     public void loadPhoto(ImageView view, Uri photoUri, int requestedExtent, boolean darkTheme,
-            DefaultImageRequest defaultImageRequest, DefaultImageProvider defaultProvider) {
+            boolean isCircular, DefaultImageRequest defaultImageRequest,
+            DefaultImageProvider defaultProvider) {
         if (photoUri == null) {
             // No photo is needed
             defaultProvider.applyDefaultImage(view, requestedExtent, darkTheme,
@@ -703,7 +744,7 @@
             } else {
 
                 loadPhotoByIdOrUri(view, Request.createFromUri(photoUri, requestedExtent,
-                        darkTheme, defaultProvider));
+                        darkTheme, isCircular, defaultProvider));
             }
         }
     }
@@ -764,12 +805,12 @@
         BitmapHolder holder = mBitmapHolderCache.get(request.getKey());
         if (holder == null) {
             // The bitmap has not been loaded ==> show default avatar
-            request.applyDefaultImage(view);
+            request.applyDefaultImage(view, request.mIsCircular);
             return false;
         }
 
         if (holder.bytes == null) {
-            request.applyDefaultImage(view);
+            request.applyDefaultImage(view, request.mIsCircular);
             return holder.fresh;
         }
 
@@ -783,7 +824,7 @@
             } else {
                 // This is bigger data. Let's send that back to the Loader so that we can
                 // inflate this in the background
-                request.applyDefaultImage(view);
+                request.applyDefaultImage(view, request.mIsCircular);
                 return false;
             }
         }
@@ -800,12 +841,13 @@
             } else {
                 layers[0] = previousDrawable;
             }
-            layers[1] = new BitmapDrawable(mContext.getResources(), cachedBitmap);
+            layers[1] = getDrawableForBitmap(mContext.getResources(), cachedBitmap, request);
             TransitionDrawable drawable = new TransitionDrawable(layers);
             view.setImageDrawable(drawable);
             drawable.startTransition(FADE_TRANSITION_DURATION);
         } else {
-            view.setImageBitmap(cachedBitmap);
+            view.setImageDrawable(
+                    getDrawableForBitmap(mContext.getResources(), cachedBitmap, request));
         }
 
         // Put the bitmap in the LRU cache. But only do this for images that are small enough
@@ -821,6 +863,22 @@
     }
 
     /**
+     * Given a bitmap, returns a drawable that is configured to display the bitmap based on the
+     * specified request.
+     */
+    private Drawable getDrawableForBitmap(Resources resources, Bitmap bitmap, Request request) {
+        if (request.mIsCircular) {
+            final RoundedBitmapDrawable drawable =
+                    RoundedBitmapDrawable.createRoundedBitmapDrawable(resources, bitmap);
+            drawable.setAntiAlias(true);
+            drawable.setCornerRadius(bitmap.getHeight() / 2);
+            return drawable;
+        } else {
+            return new BitmapDrawable(resources, bitmap);
+        }
+    }
+
+    /**
      * If necessary, decodes bytes stored in the holder to Bitmap.  As long as the
      * bitmap is held either by {@link #mBitmapCache} or by a soft reference in
      * the holder, it will not be necessary to decode the bitmap.
@@ -952,7 +1010,9 @@
         while (iterator.hasNext()) {
             ImageView view = iterator.next();
             Request key = mPendingRequests.get(view);
-            boolean loaded = loadCachedPhoto(view, key, true);
+            // TODO: Temporarily disable contact photo fading in, until issues with
+            // RoundedBitmapDrawables overlapping the default image drawables are resolved.
+            boolean loaded = loadCachedPhoto(view, key, false);
             if (loaded) {
                 iterator.remove();
             }
@@ -1010,7 +1070,8 @@
         final int smallerExtent = Math.min(bitmap.getWidth(), bitmap.getHeight());
         // We can pretend here that the extent of the photo was the size that we originally
         // requested
-        Request request = Request.createFromUri(photoUri, smallerExtent, false, DEFAULT_AVATAR);
+        Request request = Request.createFromUri(photoUri, smallerExtent, false /* darkTheme */,
+                false /* isCircular */ , DEFAULT_AVATAR);
         BitmapHolder holder = new BitmapHolder(photoBytes, smallerExtent);
         holder.bitmapRef = new SoftReference<Bitmap>(bitmap);
         mBitmapHolderCache.put(request.getKey(), holder);
@@ -1382,24 +1443,30 @@
         private final boolean mDarkTheme;
         private final int mRequestedExtent;
         private final DefaultImageProvider mDefaultProvider;
+        /**
+         * Whether or not the contact photo is to be displayed as a circle
+         */
+        private final boolean mIsCircular;
 
         private Request(long id, Uri uri, int requestedExtent, boolean darkTheme,
-                DefaultImageProvider defaultProvider) {
+                boolean isCircular, DefaultImageProvider defaultProvider) {
             mId = id;
             mUri = uri;
             mDarkTheme = darkTheme;
+            mIsCircular = isCircular;
             mRequestedExtent = requestedExtent;
             mDefaultProvider = defaultProvider;
         }
 
-        public static Request createFromThumbnailId(long id, boolean darkTheme,
+        public static Request createFromThumbnailId(long id, boolean darkTheme, boolean isCircular,
                 DefaultImageProvider defaultProvider) {
-            return new Request(id, null /* no URI */, -1, darkTheme, defaultProvider);
+            return new Request(id, null /* no URI */, -1, darkTheme, isCircular, defaultProvider);
         }
 
         public static Request createFromUri(Uri uri, int requestedExtent, boolean darkTheme,
-                DefaultImageProvider defaultProvider) {
-            return new Request(0 /* no ID */, uri, requestedExtent, darkTheme, defaultProvider);
+                boolean isCircular, DefaultImageProvider defaultProvider) {
+            return new Request(0 /* no ID */, uri, requestedExtent, darkTheme, isCircular,
+                    defaultProvider);
         }
 
         public boolean isUriRequest() {
@@ -1448,8 +1515,11 @@
             return mUri == null ? mId : mUri;
         }
 
-        public void applyDefaultImage(ImageView view) {
-            mDefaultProvider.applyDefaultImage(view, mRequestedExtent, mDarkTheme, null);
+        public void applyDefaultImage(ImageView view, boolean isCircular) {
+            final DefaultImageRequest request = isCircular
+                    ? DefaultImageRequest.EMPTY_CIRCULAR_DEFAULT_IMAGE_REQUEST
+                    : DefaultImageRequest.EMPTY_DEFAULT_IMAGE_REQUEST;
+            mDefaultProvider.applyDefaultImage(view, mRequestedExtent, mDarkTheme, request);
         }
     }
 }
diff --git a/src/com/android/contacts/common/lettertiles/LetterTileDrawable.java b/src/com/android/contacts/common/lettertiles/LetterTileDrawable.java
index 9adcca6..379ce65 100644
--- a/src/com/android/contacts/common/lettertiles/LetterTileDrawable.java
+++ b/src/com/android/contacts/common/lettertiles/LetterTileDrawable.java
@@ -70,6 +70,7 @@
     private int mContactType = TYPE_DEFAULT;
     private float mScale = 1.0f;
     private float mOffset = 0.0f;
+    private boolean mIsCircle = false;
 
     /** This should match the total number of colors defined in colors.xml for letter_tile_color */
     private static final int NUM_OF_TILE_COLORS = 8;
@@ -135,7 +136,14 @@
         sPaint.setColor(pickColor(mIdentifier));
 
         sPaint.setAlpha(mPaint.getAlpha());
-        canvas.drawRect(getBounds(), sPaint);
+        final Rect bounds = getBounds();
+        final int minDimension = Math.min(bounds.width(), bounds.height());
+
+        if (mIsCircle) {
+            canvas.drawCircle(bounds.centerX(), bounds.centerY(), minDimension / 2, sPaint);
+        } else {
+            canvas.drawRect(bounds, sPaint);
+        }
 
         // Draw letter/digit only if the first character is an english letter
         if (mDisplayName != null && isEnglishLetter(mDisplayName.charAt(0))) {
@@ -143,12 +151,10 @@
             sFirstChar[0] = Character.toUpperCase(mDisplayName.charAt(0));
 
             // Scale text by canvas bounds and user selected scaling factor
-            final int minDimension = Math.min(getBounds().width(), getBounds().height());
             sPaint.setTextSize(mScale * sLetterToTileRatio * minDimension);
             //sPaint.setTextSize(sTileLetterFontSize);
             sPaint.getTextBounds(sFirstChar, 0, 1, sRect);
             sPaint.setColor(sTileFontColor);
-            final Rect bounds = getBounds();
 
             // Draw the letter in the canvas, vertically shifted up or down by the user-defined
             // offset
@@ -244,4 +250,8 @@
     public void setContactType(int contactType) {
         mContactType = contactType;
     }
+
+    public void setIsCircular(boolean isCircle) {
+        mIsCircle = isCircle;
+    }
 }
diff --git a/src/com/android/contacts/common/list/ContactEntryListAdapter.java b/src/com/android/contacts/common/list/ContactEntryListAdapter.java
index 900cffc..d35bdc5 100644
--- a/src/com/android/contacts/common/list/ContactEntryListAdapter.java
+++ b/src/com/android/contacts/common/list/ContactEntryListAdapter.java
@@ -58,6 +58,7 @@
     private int mSortOrder;
 
     private boolean mDisplayPhotos;
+    private boolean mCircularPhotos = true;
     private boolean mQuickContactEnabled;
 
     /**
@@ -296,6 +297,14 @@
         mDisplayPhotos = displayPhotos;
     }
 
+    public boolean getCircularPhotos() {
+        return mCircularPhotos;
+    }
+
+    public void setCircularPhotos(boolean circularPhotos) {
+        mCircularPhotos = circularPhotos;
+    }
+
     public boolean isEmptyListEnabled() {
         return mEmptyListEnabled;
     }
@@ -652,7 +661,8 @@
                 getContactUri(partitionIndex, cursor, contactIdColumn, lookUpKeyColumn));
 
         if (photoId != 0 || photoUriColumn == -1) {
-            getPhotoLoader().loadThumbnail(quickContact, photoId, mDarkTheme, null);
+            getPhotoLoader().loadThumbnail(quickContact, photoId, mDarkTheme, mCircularPhotos,
+                    null);
         } else {
             final String photoUriString = cursor.getString(photoUriColumn);
             final Uri photoUri = photoUriString == null ? null : Uri.parse(photoUriString);
@@ -661,7 +671,8 @@
                 request = getDefaultImageRequestFromCursor(cursor, displayNameColumn,
                         lookUpKeyColumn);
             }
-            getPhotoLoader().loadPhoto(quickContact, photoUri, -1, mDarkTheme, request);
+            getPhotoLoader().loadPhoto(quickContact, photoUri, -1, mDarkTheme, mCircularPhotos,
+                    request);
         }
 
     }
@@ -707,10 +718,10 @@
      * @return {@link DefaultImageRequest} with the displayName and identifier fields set to the
      * display name and lookup key of the contact.
      */
-    public static DefaultImageRequest getDefaultImageRequestFromCursor(Cursor cursor,
+    public DefaultImageRequest getDefaultImageRequestFromCursor(Cursor cursor,
             int displayNameColumn, int lookupKeyColumn) {
         final String displayName = cursor.getString(displayNameColumn);
         final String lookupKey = cursor.getString(lookupKeyColumn);
-        return new DefaultImageRequest(displayName, lookupKey);
+        return new DefaultImageRequest(displayName, lookupKey, mCircularPhotos);
     }
 }
diff --git a/src/com/android/contacts/common/list/ContactListAdapter.java b/src/com/android/contacts/common/list/ContactListAdapter.java
index 4bfbdcf..fb50e3e 100644
--- a/src/com/android/contacts/common/list/ContactListAdapter.java
+++ b/src/com/android/contacts/common/list/ContactListAdapter.java
@@ -229,17 +229,19 @@
         }
 
         if (photoId != 0) {
-            getPhotoLoader().loadThumbnail(view.getPhotoView(), photoId, false, null);
+            getPhotoLoader().loadThumbnail(view.getPhotoView(), photoId, false,
+                    getCircularPhotos(), null);
         } else {
             final String photoUriString = cursor.getString(ContactQuery.CONTACT_PHOTO_URI);
             final Uri photoUri = photoUriString == null ? null : Uri.parse(photoUriString);
             DefaultImageRequest request = null;
             if (photoUri == null) {
-                String displayName = cursor.getString(ContactQuery.CONTACT_DISPLAY_NAME);
-                String lookupKey = cursor.getString(ContactQuery.CONTACT_LOOKUP_KEY);
-                request = new DefaultImageRequest(displayName, lookupKey);
+                request = getDefaultImageRequestFromCursor(cursor,
+                        ContactQuery.CONTACT_DISPLAY_NAME,
+                        ContactQuery.CONTACT_LOOKUP_KEY);
             }
-            getPhotoLoader().loadDirectoryPhoto(view.getPhotoView(), photoUri, false, request);
+            getPhotoLoader().loadDirectoryPhoto(view.getPhotoView(), photoUri, false,
+                    getCircularPhotos(), request);
         }
     }
 
diff --git a/src/com/android/contacts/common/list/ContactListItemView.java b/src/com/android/contacts/common/list/ContactListItemView.java
index 8ae26fd..d3ecd61 100644
--- a/src/com/android/contacts/common/list/ContactListItemView.java
+++ b/src/com/android/contacts/common/list/ContactListItemView.java
@@ -724,6 +724,7 @@
         }
         if (mQuickContact == null) {
             mQuickContact = new QuickContactBadge(getContext());
+            mQuickContact.setOverlay(null);
             mQuickContact.setLayoutParams(getDefaultPhotoLayoutParams());
             if (mNameTextView != null) {
                 mQuickContact.setContentDescription(getContext().getString(
diff --git a/src/com/android/contacts/common/list/ContactTileView.java b/src/com/android/contacts/common/list/ContactTileView.java
index a7d3d35..e101490 100644
--- a/src/com/android/contacts/common/list/ContactTileView.java
+++ b/src/com/android/contacts/common/list/ContactTileView.java
@@ -129,7 +129,7 @@
                 configureViewForImage(entry.photoUri == null);
                 if (mPhoto != null) {
                     mPhotoManager.loadPhoto(mPhoto, entry.photoUri, getApproximateImageSize(),
-                            isDarkTheme(), request);
+                            isDarkTheme(), false /* isCircular */, request);
 
                     if (mQuickContact != null) {
                         mQuickContact.assignContactUri(mLookupUri);
@@ -137,7 +137,8 @@
                 } else if (mQuickContact != null) {
                     mQuickContact.assignContactUri(mLookupUri);
                     mPhotoManager.loadPhoto(mQuickContact, entry.photoUri,
-                            getApproximateImageSize(), isDarkTheme(), request);
+                            getApproximateImageSize(), isDarkTheme(), false /* isCircular */,
+                            request);
                 }
             } else {
                 Log.w(TAG, "contactPhotoManager not set");
@@ -206,7 +207,7 @@
      * as desired, or {@code null}.
      */
     protected DefaultImageRequest getDefaultImageRequest(String displayName, String lookupKey) {
-        return new DefaultImageRequest(displayName, lookupKey);
+        return new DefaultImageRequest(displayName, lookupKey, false);
     }
 
     public interface Listener {
diff --git a/src/com/android/contacts/common/list/PhoneNumberListAdapter.java b/src/com/android/contacts/common/list/PhoneNumberListAdapter.java
index 861f739..0d00fa3 100644
--- a/src/com/android/contacts/common/list/PhoneNumberListAdapter.java
+++ b/src/com/android/contacts/common/list/PhoneNumberListAdapter.java
@@ -421,7 +421,8 @@
         }
 
         if (photoId != 0) {
-            getPhotoLoader().loadThumbnail(view.getPhotoView(), photoId, false, null);
+            getPhotoLoader().loadThumbnail(view.getPhotoView(), photoId, false,
+                    getCircularPhotos(), null);
         } else {
             final String photoUriString = cursor.getString(PhoneQuery.PHOTO_URI);
             final Uri photoUri = photoUriString == null ? null : Uri.parse(photoUriString);
@@ -430,9 +431,10 @@
             if (photoUri == null) {
                 final String displayName = cursor.getString(PhoneQuery.DISPLAY_NAME);
                 final String lookupKey = cursor.getString(PhoneQuery.LOOKUP_KEY);
-                request = new DefaultImageRequest(displayName, lookupKey);
+                request = new DefaultImageRequest(displayName, lookupKey, false);
             }
-            getPhotoLoader().loadDirectoryPhoto(view.getPhotoView(), photoUri, false, request);
+            getPhotoLoader().loadDirectoryPhoto(view.getPhotoView(), photoUri, false,
+                    getCircularPhotos(), request);
         }
     }
 
diff --git a/src/com/android/contacts/common/list/ShortcutIntentBuilder.java b/src/com/android/contacts/common/list/ShortcutIntentBuilder.java
index 21819bb..b06e44e 100644
--- a/src/com/android/contacts/common/list/ShortcutIntentBuilder.java
+++ b/src/com/android/contacts/common/list/ShortcutIntentBuilder.java
@@ -254,7 +254,7 @@
             return new BitmapDrawable(mContext.getResources(), bitmap);
         } else {
             return ContactPhotoManager.getDefaultAvatarDrawableForContact(mContext.getResources(),
-                    false, new DefaultImageRequest(displayName, lookupKey));
+                    false, new DefaultImageRequest(displayName, lookupKey, false));
         }
     }