Fixing excessive resource use when a bogus contact photo id is encountered.

ContactPhotoLoader would repeatedly attempt to load a missing
photo when the photo ID was invalid.

Change-Id: Ibb19a5ce6cad65d1d48bd06ca8e00ec85eee6b5a
diff --git a/src/com/android/contacts/ContactPhotoLoader.java b/src/com/android/contacts/ContactPhotoLoader.java
index 70f3014..e82882c 100644
--- a/src/com/android/contacts/ContactPhotoLoader.java
+++ b/src/com/android/contacts/ContactPhotoLoader.java
@@ -44,6 +44,8 @@
  */
 public class ContactPhotoLoader implements Callback {
 
+    private static final String LOADER_THREAD_NAME = "ContactPhotoLoader";
+
     /**
      * Type of message sent by the UI thread to itself to indicate that some photos
      * need to be loaded.
@@ -58,6 +60,8 @@
 
     private static final String[] EMPTY_STRING_ARRAY = new String[0];
 
+    private final String[] COLUMNS = new String[] { Photo._ID, Photo.PHOTO };
+
     /**
      * The resource ID of the image to be used when the photo is unavailable or being
      * loaded.
@@ -299,8 +303,10 @@
     /**
      * Populates an array of photo IDs that need to be loaded.
      */
-    private void obtainPhotoIdsToLoad(ArrayList<String> photoIds) {
+    private void obtainPhotoIdsToLoad(ArrayList<Long> photoIds,
+            ArrayList<String> photoIdsAsStrings) {
         photoIds.clear();
+        photoIdsAsStrings.clear();
 
         /*
          * Since the call is made from the loader thread, the map could be
@@ -317,7 +323,8 @@
             if (holder.state == BitmapHolder.NEEDED) {
                 // Assuming atomic behavior
                 holder.state = BitmapHolder.LOADING;
-                photoIds.add(id.toString());
+                photoIds.add(id);
+                photoIdsAsStrings.add(id.toString());
             }
         }
     }
@@ -326,12 +333,10 @@
      * The thread that performs loading of photos from the database.
      */
     private class LoaderThread extends HandlerThread implements Callback {
-        private static final String LOADER_THREAD_NAME = "ContactPhotoLoader";
-        private final String[] COLUMNS = new String[] { Photo._ID, Photo.PHOTO };
-
         private final ContentResolver mResolver;
         private final StringBuilder mStringBuilder = new StringBuilder();
-        private final ArrayList<String> mPhotoIds = Lists.newArrayList();
+        private final ArrayList<Long> mPhotoIds = Lists.newArrayList();
+        private final ArrayList<String> mPhotoIdsAsStrings = Lists.newArrayList();
         private Handler mLoaderThreadHandler;
 
         public LoaderThread(ContentResolver resolver) {
@@ -360,7 +365,7 @@
         }
 
         private void loadPhotosFromDatabase() {
-            obtainPhotoIdsToLoad(mPhotoIds);
+            obtainPhotoIdsToLoad(mPhotoIds, mPhotoIdsAsStrings);
 
             int count = mPhotoIds.size();
             if (count == 0) {
@@ -382,7 +387,7 @@
                 cursor = mResolver.query(Data.CONTENT_URI,
                         COLUMNS,
                         mStringBuilder.toString(),
-                        mPhotoIds.toArray(EMPTY_STRING_ARRAY),
+                        mPhotoIdsAsStrings.toArray(EMPTY_STRING_ARRAY),
                         null);
 
                 if (cursor != null) {
@@ -390,6 +395,7 @@
                         Long id = cursor.getLong(0);
                         byte[] bytes = cursor.getBlob(1);
                         cacheBitmap(id, bytes);
+                        mPhotoIds.remove(id);
                     }
                 }
             } finally {
@@ -397,6 +403,12 @@
                     cursor.close();
                 }
             }
+
+            // Remaining photos were not found in the database - mark the cache accordingly.
+            count = mPhotoIds.size();
+            for (int i = 0; i < count; i++) {
+                cacheBitmap(mPhotoIds.get(i), null);
+            }
         }
     }
 }