Don't recache in ContactPhotoManager unnecessarily

The ContactPhotoManager currently constantly tries to recache
bitmaps that were unable to load, or were too big to fit in the
cache. This can cause unnecessary CPU/network usage. Use a dummy
object instead to indicate that the bitmap should not be reloaded
for the given URI.

Bug: 21423350
Change-Id: I32c02efce3592b81c581adcfda39e1e668cefa60
diff --git a/src/com/android/contacts/common/ContactPhotoManager.java b/src/com/android/contacts/common/ContactPhotoManager.java
index dce6a77..7a8f138 100644
--- a/src/com/android/contacts/common/ContactPhotoManager.java
+++ b/src/com/android/contacts/common/ContactPhotoManager.java
@@ -598,6 +598,17 @@
     private static final String[] COLUMNS = new String[] { Photo._ID, Photo.PHOTO };
 
     /**
+     * Dummy object used to indicate that a bitmap for a given key could not be stored in the
+     * cache.
+     */
+    private static final BitmapHolder BITMAP_UNAVAILABLE;
+
+    static {
+        BITMAP_UNAVAILABLE = new BitmapHolder(new byte[0], 0);
+        BITMAP_UNAVAILABLE.bitmapRef = new SoftReference<Bitmap>(null);
+    }
+
+    /**
      * Maintains the state of a particular photo.
      */
     private static class BitmapHolder {
@@ -903,7 +914,9 @@
         if (DEBUG) Log.d(TAG, "refreshCache");
         mBitmapHolderCacheAllUnfresh = true;
         for (BitmapHolder holder : mBitmapHolderCache.snapshot().values()) {
-            holder.fresh = false;
+            if (holder != BITMAP_UNAVAILABLE) {
+                holder.fresh = false;
+            }
         }
     }
 
@@ -1186,7 +1199,16 @@
             inflateBitmap(holder, requestedExtent);
         }
 
-        mBitmapHolderCache.put(key, holder);
+        if (bytes != null) {
+            mBitmapHolderCache.put(key, holder);
+            if (mBitmapHolderCache.get(key) != holder) {
+                Log.w(TAG, "Bitmap too big to fit in cache.");
+                mBitmapHolderCache.put(key, BITMAP_UNAVAILABLE);
+            }
+        } else {
+            mBitmapHolderCache.put(key, BITMAP_UNAVAILABLE);
+        }
+
         mBitmapHolderCacheAllUnfresh = false;
     }