Merge "Fixed missing "No Contacts" message"
diff --git a/res/drawable-hdpi/ic_contact_picture.png b/res/drawable-hdpi/ic_contact_picture.png
deleted file mode 100755
index e29e63a..0000000
--- a/res/drawable-hdpi/ic_contact_picture.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_contact_picture_180_holo_dark.png b/res/drawable-hdpi/ic_contact_picture_180_holo_dark.png
new file mode 100644
index 0000000..278c121
--- /dev/null
+++ b/res/drawable-hdpi/ic_contact_picture_180_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_contact_picture_180_holo_light.png b/res/drawable-hdpi/ic_contact_picture_180_holo_light.png
new file mode 100644
index 0000000..0ce49fe
--- /dev/null
+++ b/res/drawable-hdpi/ic_contact_picture_180_holo_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_contact_picture_holo_dark.png b/res/drawable-hdpi/ic_contact_picture_holo_dark.png
new file mode 100644
index 0000000..de9157e
--- /dev/null
+++ b/res/drawable-hdpi/ic_contact_picture_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_contact_picture_holo_light.png b/res/drawable-hdpi/ic_contact_picture_holo_light.png
new file mode 100644
index 0000000..2eef7b5
--- /dev/null
+++ b/res/drawable-hdpi/ic_contact_picture_holo_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher_contacts.png b/res/drawable-hdpi/ic_launcher_contacts.png
index 3e1ea44..f2657dc 100644
--- a/res/drawable-hdpi/ic_launcher_contacts.png
+++ b/res/drawable-hdpi/ic_launcher_contacts.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher_phone.png b/res/drawable-hdpi/ic_launcher_phone.png
index 0943ce5..37ffb9c 100644
--- a/res/drawable-hdpi/ic_launcher_phone.png
+++ b/res/drawable-hdpi/ic_launcher_phone.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher_shortcut_contact.png b/res/drawable-hdpi/ic_launcher_shortcut_contact.png
index d86b264..2dc1014 100644
--- a/res/drawable-hdpi/ic_launcher_shortcut_contact.png
+++ b/res/drawable-hdpi/ic_launcher_shortcut_contact.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher_shortcut_directdial.png b/res/drawable-hdpi/ic_launcher_shortcut_directdial.png
index e7ff8f8..b5c0dd9 100644
--- a/res/drawable-hdpi/ic_launcher_shortcut_directdial.png
+++ b/res/drawable-hdpi/ic_launcher_shortcut_directdial.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher_shortcut_directmessage.png b/res/drawable-hdpi/ic_launcher_shortcut_directmessage.png
index 5170a75..10720e4 100644
--- a/res/drawable-hdpi/ic_launcher_shortcut_directmessage.png
+++ b/res/drawable-hdpi/ic_launcher_shortcut_directmessage.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_contact_picture.png b/res/drawable-mdpi/ic_contact_picture.png
deleted file mode 100644
index faa3dc0..0000000
--- a/res/drawable-mdpi/ic_contact_picture.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_contact_picture_180_holo_dark.png b/res/drawable-mdpi/ic_contact_picture_180_holo_dark.png
new file mode 100644
index 0000000..cc5dd09
--- /dev/null
+++ b/res/drawable-mdpi/ic_contact_picture_180_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_contact_picture_180_holo_light.png b/res/drawable-mdpi/ic_contact_picture_180_holo_light.png
new file mode 100644
index 0000000..77539d3
--- /dev/null
+++ b/res/drawable-mdpi/ic_contact_picture_180_holo_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_contact_picture_holo_dark.png b/res/drawable-mdpi/ic_contact_picture_holo_dark.png
new file mode 100644
index 0000000..fb365c4
--- /dev/null
+++ b/res/drawable-mdpi/ic_contact_picture_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_contact_picture_holo_light.png b/res/drawable-mdpi/ic_contact_picture_holo_light.png
new file mode 100644
index 0000000..6c7cb61
--- /dev/null
+++ b/res/drawable-mdpi/ic_contact_picture_holo_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_contacts.png b/res/drawable-mdpi/ic_launcher_contacts.png
index 618630f..6b06cac 100644
--- a/res/drawable-mdpi/ic_launcher_contacts.png
+++ b/res/drawable-mdpi/ic_launcher_contacts.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_phone.png b/res/drawable-mdpi/ic_launcher_phone.png
index 724f94a..5ef8c40 100644
--- a/res/drawable-mdpi/ic_launcher_phone.png
+++ b/res/drawable-mdpi/ic_launcher_phone.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_shortcut_contact.png b/res/drawable-mdpi/ic_launcher_shortcut_contact.png
index 20d359d..bce245c 100644
--- a/res/drawable-mdpi/ic_launcher_shortcut_contact.png
+++ b/res/drawable-mdpi/ic_launcher_shortcut_contact.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_shortcut_directdial.png b/res/drawable-mdpi/ic_launcher_shortcut_directdial.png
index 7081c08..e4649cf 100644
--- a/res/drawable-mdpi/ic_launcher_shortcut_directdial.png
+++ b/res/drawable-mdpi/ic_launcher_shortcut_directdial.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_shortcut_directmessage.png b/res/drawable-mdpi/ic_launcher_shortcut_directmessage.png
index 374c7c4..4be34e5 100644
--- a/res/drawable-mdpi/ic_launcher_shortcut_directmessage.png
+++ b/res/drawable-mdpi/ic_launcher_shortcut_directmessage.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_contact_picture.png b/res/drawable-xhdpi/ic_contact_picture.png
deleted file mode 100644
index e551140..0000000
--- a/res/drawable-xhdpi/ic_contact_picture.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_contact_picture_180_holo_dark.png b/res/drawable-xhdpi/ic_contact_picture_180_holo_dark.png
new file mode 100644
index 0000000..b8ee922
--- /dev/null
+++ b/res/drawable-xhdpi/ic_contact_picture_180_holo_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_contact_picture_180_holo_light.png b/res/drawable-xhdpi/ic_contact_picture_180_holo_light.png
new file mode 100644
index 0000000..9727b45
--- /dev/null
+++ b/res/drawable-xhdpi/ic_contact_picture_180_holo_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_contact_picture_holo_dark.png b/res/drawable-xhdpi/ic_contact_picture_holo_dark.png
new file mode 100644
index 0000000..9fa0698
--- /dev/null
+++ b/res/drawable-xhdpi/ic_contact_picture_holo_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_contact_picture_holo_light.png b/res/drawable-xhdpi/ic_contact_picture_holo_light.png
new file mode 100644
index 0000000..1a2bfde
--- /dev/null
+++ b/res/drawable-xhdpi/ic_contact_picture_holo_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher_contacts.png b/res/drawable-xhdpi/ic_launcher_contacts.png
index 1bb0a3f..a2ba3bc 100644
--- a/res/drawable-xhdpi/ic_launcher_contacts.png
+++ b/res/drawable-xhdpi/ic_launcher_contacts.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher_phone.png b/res/drawable-xhdpi/ic_launcher_phone.png
index 6a454da..2226b7b 100644
--- a/res/drawable-xhdpi/ic_launcher_phone.png
+++ b/res/drawable-xhdpi/ic_launcher_phone.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher_shortcut_contact.png b/res/drawable-xhdpi/ic_launcher_shortcut_contact.png
index 94c7da5..a5a71fa 100644
--- a/res/drawable-xhdpi/ic_launcher_shortcut_contact.png
+++ b/res/drawable-xhdpi/ic_launcher_shortcut_contact.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher_shortcut_directdial.png b/res/drawable-xhdpi/ic_launcher_shortcut_directdial.png
index 42f8f0a..b839084 100644
--- a/res/drawable-xhdpi/ic_launcher_shortcut_directdial.png
+++ b/res/drawable-xhdpi/ic_launcher_shortcut_directdial.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher_shortcut_directmessage.png b/res/drawable-xhdpi/ic_launcher_shortcut_directmessage.png
index babcc02..35e1467 100644
--- a/res/drawable-xhdpi/ic_launcher_shortcut_directmessage.png
+++ b/res/drawable-xhdpi/ic_launcher_shortcut_directmessage.png
Binary files differ
diff --git a/res/layout-w470dp/contact_detail_fragment.xml b/res/layout-w470dp/contact_detail_fragment.xml
index 415bb56..211af3b 100644
--- a/res/layout-w470dp/contact_detail_fragment.xml
+++ b/res/layout-w470dp/contact_detail_fragment.xml
@@ -35,7 +35,8 @@
         android:orientation="horizontal"
         android:layout_width="match_parent"
         android:layout_above="@id/contact_quick_fix"
-        android:layout_height="match_parent" >
+        android:layout_height="match_parent"
+        android:background="@color/background_primary" >
 
         <ImageView android:id="@+id/photo"
             android:scaleType="centerCrop"
diff --git a/res/layout/confirm_add_detail_activity.xml b/res/layout/confirm_add_detail_activity.xml
index 6bbaac5..70e2b47 100644
--- a/res/layout/confirm_add_detail_activity.xml
+++ b/res/layout/confirm_add_detail_activity.xml
@@ -35,7 +35,7 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:scaleType="centerCrop"
-            android:src="@drawable/ic_contact_picture" />
+            android:src="@drawable/ic_contact_picture_180_holo_light" />
 
         <View
             android:id="@+id/photo_text_bar"
diff --git a/res/layout/contact_tile_frequent_phone.xml b/res/layout/contact_tile_frequent_phone.xml
index 6b920e8..26c221c 100644
--- a/res/layout/contact_tile_frequent_phone.xml
+++ b/res/layout/contact_tile_frequent_phone.xml
@@ -16,7 +16,7 @@
 <view
     android:id="@+id/contact_tile_frequent_phone"
     xmlns:android="http://schemas.android.com/apk/res/android"
-    class="com.android.contacts.list.ContactTileView"
+    class="com.android.contacts.list.ContactTileDarkFrequentView"
     android:focusable="true"
     android:background="?android:attr/selectableItemBackground"
     android:nextFocusLeft="@+id/contact_tile_quick"
diff --git a/res/layout/contact_tile_starred_secondary_target.xml b/res/layout/contact_tile_starred_secondary_target.xml
index 2ce59c5..27ef3a3 100644
--- a/res/layout/contact_tile_starred_secondary_target.xml
+++ b/res/layout/contact_tile_starred_secondary_target.xml
@@ -69,7 +69,8 @@
             android:paddingRight="8dip"
             android:paddingLeft="8dip"
             android:layout_alignParentBottom="true"
-            android:layout_alignParentRight="true" />
+            android:layout_alignParentRight="true"
+            android:contentDescription="@string/description_view_contact_detail" />
 
     </RelativeLayout>
 
diff --git a/res/layout/item_photo_editor.xml b/res/layout/item_photo_editor.xml
index 7cfb35d..a22a535 100644
--- a/res/layout/item_photo_editor.xml
+++ b/res/layout/item_photo_editor.xml
@@ -24,7 +24,7 @@
         android:id="@+id/photo"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:src="@drawable/ic_contact_picture"
+        android:src="@drawable/ic_contact_picture_holo_light"
         android:cropToPadding="true"
         android:scaleType="centerCrop"
         android:gravity="left"
diff --git a/res/mipmap-hdpi/ic_launcher_shortcut_contact.png b/res/mipmap-hdpi/ic_launcher_shortcut_contact.png
index d86b264..c867181 100644
--- a/res/mipmap-hdpi/ic_launcher_shortcut_contact.png
+++ b/res/mipmap-hdpi/ic_launcher_shortcut_contact.png
Binary files differ
diff --git a/res/mipmap-hdpi/ic_launcher_shortcut_directdial.png b/res/mipmap-hdpi/ic_launcher_shortcut_directdial.png
index e7ff8f8..c515815 100644
--- a/res/mipmap-hdpi/ic_launcher_shortcut_directdial.png
+++ b/res/mipmap-hdpi/ic_launcher_shortcut_directdial.png
Binary files differ
diff --git a/res/mipmap-hdpi/ic_launcher_shortcut_directmessage.png b/res/mipmap-hdpi/ic_launcher_shortcut_directmessage.png
index 5170a75..a347fa1 100644
--- a/res/mipmap-hdpi/ic_launcher_shortcut_directmessage.png
+++ b/res/mipmap-hdpi/ic_launcher_shortcut_directmessage.png
Binary files differ
diff --git a/res/mipmap-mdpi/ic_launcher_shortcut_contact.png b/res/mipmap-mdpi/ic_launcher_shortcut_contact.png
index 20d359d..dd3c8ff 100644
--- a/res/mipmap-mdpi/ic_launcher_shortcut_contact.png
+++ b/res/mipmap-mdpi/ic_launcher_shortcut_contact.png
Binary files differ
diff --git a/res/mipmap-mdpi/ic_launcher_shortcut_directdial.png b/res/mipmap-mdpi/ic_launcher_shortcut_directdial.png
index 7081c08..1dfe8cc 100644
--- a/res/mipmap-mdpi/ic_launcher_shortcut_directdial.png
+++ b/res/mipmap-mdpi/ic_launcher_shortcut_directdial.png
Binary files differ
diff --git a/res/mipmap-mdpi/ic_launcher_shortcut_directmessage.png b/res/mipmap-mdpi/ic_launcher_shortcut_directmessage.png
index 374c7c4..c7dc525 100644
--- a/res/mipmap-mdpi/ic_launcher_shortcut_directmessage.png
+++ b/res/mipmap-mdpi/ic_launcher_shortcut_directmessage.png
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_launcher_shortcut_contact.png b/res/mipmap-xhdpi/ic_launcher_shortcut_contact.png
index 94c7da5..baeb41f 100644
--- a/res/mipmap-xhdpi/ic_launcher_shortcut_contact.png
+++ b/res/mipmap-xhdpi/ic_launcher_shortcut_contact.png
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_launcher_shortcut_directdial.png b/res/mipmap-xhdpi/ic_launcher_shortcut_directdial.png
index 42f8f0a..39d039a 100644
--- a/res/mipmap-xhdpi/ic_launcher_shortcut_directdial.png
+++ b/res/mipmap-xhdpi/ic_launcher_shortcut_directdial.png
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_launcher_shortcut_directmessage.png b/res/mipmap-xhdpi/ic_launcher_shortcut_directmessage.png
index babcc02..7dd5d39 100644
--- a/res/mipmap-xhdpi/ic_launcher_shortcut_directmessage.png
+++ b/res/mipmap-xhdpi/ic_launcher_shortcut_directmessage.png
Binary files differ
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index 7d9b758..b7ccffc 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -611,7 +611,7 @@
 
     /** Load the contact photos and places them in the corresponding views. */
     private void loadContactPhotos(Uri photoUri) {
-        mContactPhotoManager.loadPhoto(mContactBackgroundView, photoUri);
+        mContactPhotoManager.loadPhoto(mContactBackgroundView, photoUri, true, true);
     }
 
     private String getVoicemailNumber() {
diff --git a/src/com/android/contacts/ContactPhotoManager.java b/src/com/android/contacts/ContactPhotoManager.java
index eb9531a..b2ceffa 100644
--- a/src/com/android/contacts/ContactPhotoManager.java
+++ b/src/com/android/contacts/ContactPhotoManager.java
@@ -17,6 +17,7 @@
 package com.android.contacts;
 
 import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.util.UriUtils;
 import com.google.android.collect.Lists;
 import com.google.android.collect.Sets;
 
@@ -59,11 +60,12 @@
 
     public static final String CONTACT_PHOTO_SERVICE = "contactPhotos";
 
-    /**
-     * The resource ID of the image to be used when the photo is unavailable or being
-     * loaded.
-     */
-    protected final int mDefaultResourceId = R.drawable.ic_contact_picture;
+    public static int getDefaultAvatarResId(boolean hires, boolean darkTheme) {
+        if (hires && darkTheme) return R.drawable.ic_contact_picture_180_holo_dark;
+        if (hires) return R.drawable.ic_contact_picture_180_holo_light;
+        if (darkTheme) return R.drawable.ic_contact_picture_holo_dark;
+        return R.drawable.ic_contact_picture_holo_light;
+    }
 
     /**
      * Requests the singleton instance of {@link AccountTypeManager} with data bound from
@@ -89,14 +91,14 @@
      * it is displayed immediately.  Otherwise a request is sent to load the photo
      * from the database.
      */
-    public abstract void loadPhoto(ImageView view, long photoId);
+    public abstract void loadPhoto(ImageView view, long photoId, boolean hires, boolean darkTheme);
 
     /**
      * Load photo into the supplied image view.  If the photo is already cached,
      * it is displayed immediately.  Otherwise a request is sent to load the photo
      * from the location specified by the URI.
      */
-    public abstract void loadPhoto(ImageView view, Uri photoUri);
+    public abstract void loadPhoto(ImageView view, Uri photoUri, boolean hires, boolean darkTheme);
 
     /**
      * Remove photo from the supplied image view. This also cancels current pending load request
@@ -185,11 +187,11 @@
     private final LruCache<Object, Bitmap> mBitmapCache;
 
     /**
-     * A map from ImageView to the corresponding photo ID. Please note that this
-     * photo ID may change before the photo loading request is started.
+     * A map from ImageView to the corresponding photo ID or uri, encapsulated in a request.
+     * The request may swapped out before the photo loading request is started.
      */
-    private final ConcurrentHashMap<ImageView, Object> mPendingRequests =
-            new ConcurrentHashMap<ImageView, Object>();
+    private final ConcurrentHashMap<ImageView, Request> mPendingRequests =
+            new ConcurrentHashMap<ImageView, Request>();
 
     /**
      * Handler for messages sent to the UI thread.
@@ -234,33 +236,33 @@
     }
 
     @Override
-    public void loadPhoto(ImageView view, long photoId) {
+    public void loadPhoto(ImageView view, long photoId, boolean hires, boolean darkTheme) {
         if (photoId == 0) {
             // No photo is needed
-            view.setImageResource(mDefaultResourceId);
+            view.setImageResource(getDefaultAvatarResId(hires, darkTheme));
             mPendingRequests.remove(view);
         } else {
-            loadPhotoByIdOrUri(view, photoId);
+            loadPhotoByIdOrUri(view, Request.createFromId(photoId, hires, darkTheme));
         }
     }
 
     @Override
-    public void loadPhoto(ImageView view, Uri photoUri) {
+    public void loadPhoto(ImageView view, Uri photoUri, boolean hires, boolean darkTheme) {
         if (photoUri == null) {
             // No photo is needed
-            view.setImageResource(mDefaultResourceId);
+            view.setImageResource(getDefaultAvatarResId(hires, darkTheme));
             mPendingRequests.remove(view);
         } else {
-            loadPhotoByIdOrUri(view, photoUri);
+            loadPhotoByIdOrUri(view, Request.createFromUri(photoUri, hires, darkTheme));
         }
     }
 
-    private void loadPhotoByIdOrUri(ImageView view, Object key) {
-        boolean loaded = loadCachedPhoto(view, key);
+    private void loadPhotoByIdOrUri(ImageView view, Request request) {
+        boolean loaded = loadCachedPhoto(view, request);
         if (loaded) {
             mPendingRequests.remove(view);
         } else {
-            mPendingRequests.put(view, key);
+            mPendingRequests.put(view, request);
             if (!mPaused) {
                 // Send a request to start loading photos
                 requestLoading();
@@ -286,16 +288,16 @@
      *
      * @return false if the photo needs to be (re)loaded from the provider.
      */
-    private boolean loadCachedPhoto(ImageView view, Object key) {
-        BitmapHolder holder = mBitmapHolderCache.get(key);
+    private boolean loadCachedPhoto(ImageView view, Request request) {
+        BitmapHolder holder = mBitmapHolderCache.get(request.getKey());
         if (holder == null) {
             // The bitmap has not been loaded - should display the placeholder image.
-            view.setImageResource(mDefaultResourceId);
+            view.setImageResource(getDefaultAvatarResId(request.isHires(), request.isDarkTheme()));
             return false;
         }
 
         if (holder.bytes == null) {
-            view.setImageResource(mDefaultResourceId);
+            view.setImageResource(getDefaultAvatarResId(request.isHires(), request.isDarkTheme()));
             return holder.fresh;
         }
 
@@ -305,7 +307,7 @@
         view.setImageBitmap(holder.bitmap);
 
         // Put the bitmap in the LRU cache
-        mBitmapCache.put(key, holder.bitmap);
+        mBitmapCache.put(request, holder.bitmap);
 
         // Soften the reference
         holder.bitmap = null;
@@ -376,6 +378,7 @@
     /**
      * Processes requests on the main thread.
      */
+    @Override
     public boolean handleMessage(Message msg) {
         switch (msg.what) {
             case MESSAGE_REQUEST_LOADING: {
@@ -412,7 +415,7 @@
         Iterator<ImageView> iterator = mPendingRequests.keySet().iterator();
         while (iterator.hasNext()) {
             ImageView view = iterator.next();
-            Object key = mPendingRequests.get(view);
+            Request key = mPendingRequests.get(view);
             boolean loaded = loadCachedPhoto(view, key);
             if (loaded) {
                 iterator.remove();
@@ -469,16 +472,16 @@
          * concurrent change, we will need to check the map again once loading
          * is complete.
          */
-        Iterator<Object> iterator = mPendingRequests.values().iterator();
+        Iterator<Request> iterator = mPendingRequests.values().iterator();
         while (iterator.hasNext()) {
-            Object key = iterator.next();
-            BitmapHolder holder = mBitmapHolderCache.get(key);
+            Request request = iterator.next();
+            BitmapHolder holder = mBitmapHolderCache.get(request);
             if (holder == null || !holder.fresh) {
-                if (key instanceof Long) {
-                    photoIds.add((Long)key);
-                    photoIdsAsStrings.add(key.toString());
+                if (request.isUriRequest()) {
+                    uris.add(request.mUri);
                 } else {
-                    uris.add((Uri)key);
+                    photoIds.add(request.mId);
+                    photoIdsAsStrings.add(String.valueOf(request.mId));
                 }
             }
         }
@@ -571,6 +574,7 @@
          * Receives the above message, loads photos and then sends a message
          * to the main thread to process them.
          */
+        @Override
         public boolean handleMessage(Message msg) {
             switch (msg.what) {
                 case MESSAGE_PRELOAD_PHOTOS:
@@ -777,4 +781,65 @@
             }
         }
     }
+
+    /**
+     * A holder for either a Uri or an id and a flag whether this was requested for the dark or
+     * light theme
+     */
+    private static final class Request {
+        private final long mId;
+        private final Uri mUri;
+        private final boolean mDarkTheme;
+        private final boolean mHires;
+
+        private Request(long id, Uri uri, boolean hires, boolean darkTheme) {
+            mId = id;
+            mUri = uri;
+            mDarkTheme = darkTheme;
+            mHires = hires;
+        }
+
+        public static Request createFromId(long id, boolean hires, boolean darkTheme) {
+            return new Request(id, null /* no URI */, hires, darkTheme);
+        }
+
+        public static Request createFromUri(Uri uri, boolean hires, boolean darkTheme) {
+            return new Request(0 /* no ID */, uri, hires, darkTheme);
+        }
+
+        public boolean isDarkTheme() {
+            return mDarkTheme;
+        }
+
+        public boolean isHires() {
+            return mHires;
+        }
+
+        public boolean isUriRequest() {
+            return mUri != null;
+        }
+
+        @Override
+        public int hashCode() {
+            if (mUri != null) return mUri.hashCode();
+
+            // copied over from Long.hashCode()
+            return (int) (mId ^ (mId >>> 32));
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof Request)) return false;
+            final Request that = (Request) o;
+            // Don't compare equality of mHires and mDarkTheme fields because these are only used
+            // in the default contact photo case. When the contact does have a photo, the contact
+            // photo is the same regardless of mHires and mDarkTheme, so we shouldn't need to put
+            // the photo request on the queue twice.
+            return mId == that.mId && UriUtils.areEqual(mUri, that.mUri);
+        }
+
+        public Object getKey() {
+            return mUri == null ? mId : mUri;
+        }
+    }
 }
diff --git a/src/com/android/contacts/NfcHandler.java b/src/com/android/contacts/NfcHandler.java
index e3e94a9..ee3e002 100644
--- a/src/com/android/contacts/NfcHandler.java
+++ b/src/com/android/contacts/NfcHandler.java
@@ -26,6 +26,7 @@
 import android.nfc.NfcAdapter;
 import android.nfc.NfcEvent;
 import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Profile;
 
 import android.util.Log;
 
@@ -43,9 +44,9 @@
   */
 public class NfcHandler implements NfcAdapter.CreateNdefMessageCallback {
 
-    static final String TAG = "ContactNfcHandler";
-
-    final ContactDetailFragment mContactFragment;
+    private static final String TAG = "ContactNfcHandler";
+    private static final String PROFILE_LOOKUP_KEY = "profile";
+    private final ContactDetailFragment mContactFragment;
 
     public static void register(Activity activity, ContactDetailFragment contactFragment) {
         NfcAdapter adapter = NfcAdapter.getDefaultAdapter(activity.getApplicationContext());
@@ -66,10 +67,19 @@
         ContentResolver resolver = mContactFragment.getActivity().getContentResolver();
         if (contactUri != null) {
             final String lookupKey = Uri.encode(contactUri.getPathSegments().get(2));
-            final Uri shareUri = Contacts.CONTENT_VCARD_URI.buildUpon().
-                    appendPath(lookupKey).
-                    appendQueryParameter(Contacts.QUERY_PARAMETER_VCARD_NO_PHOTO, "true").
-                    build();
+            final Uri shareUri;
+            // TODO find out where to get this constant from, or find another way
+            // of determining this.
+            if (lookupKey.equals(PROFILE_LOOKUP_KEY)) {
+                shareUri = Profile.CONTENT_VCARD_URI.buildUpon().
+                appendQueryParameter(Contacts.QUERY_PARAMETER_VCARD_NO_PHOTO, "true").
+                build();
+            } else {
+                shareUri = Contacts.CONTENT_VCARD_URI.buildUpon().
+                appendPath(lookupKey).
+                appendQueryParameter(Contacts.QUERY_PARAMETER_VCARD_NO_PHOTO, "true").
+                build();
+            }
             ByteArrayOutputStream ndefBytes = new ByteArrayOutputStream();
             byte[] buffer = new byte[1024];
             int r;
diff --git a/src/com/android/contacts/activities/DialtactsActivity.java b/src/com/android/contacts/activities/DialtactsActivity.java
index 25f6fc2..50d6f17 100644
--- a/src/com/android/contacts/activities/DialtactsActivity.java
+++ b/src/com/android/contacts/activities/DialtactsActivity.java
@@ -45,6 +45,7 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.preference.PreferenceManager;
 import android.provider.CallLog.Calls;
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Intents.UI;
@@ -94,12 +95,11 @@
 
     private static final int TAB_INDEX_COUNT = 3;
 
-    /** Name of the dialtacts shared preferences */
-    static final String PREFS_DIALTACTS = "dialtacts";
-    static final boolean PREF_FAVORITES_AS_CONTACTS_DEFAULT = false;
+    private SharedPreferences mPrefs;
 
     /** Last manually selected tab index */
-    private static final String PREF_LAST_MANUALLY_SELECTED_TAB = "last_manually_selected_tab";
+    private static final String PREF_LAST_MANUALLY_SELECTED_TAB =
+            "DialtactsActivity_last_manually_selected_tab";
     private static final int PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT = TAB_INDEX_DIALER;
 
     /**
@@ -391,8 +391,8 @@
         getActionBar().setDisplayShowHomeEnabled(false);
 
         // Load the last manually loaded tab
-        final SharedPreferences prefs = getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE);
-        mLastManuallySelectedFragment = prefs.getInt(PREF_LAST_MANUALLY_SELECTED_TAB,
+        mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+        mLastManuallySelectedFragment = mPrefs.getInt(PREF_LAST_MANUALLY_SELECTED_TAB,
                 PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT);
         if (mLastManuallySelectedFragment >= TAB_INDEX_COUNT) {
             // Stored value may have exceeded the number of current tabs. Reset it.
@@ -482,6 +482,7 @@
             mSearchFragment = (PhoneNumberPickerFragment) fragment;
             mSearchFragment.setOnPhoneNumberPickerActionListener(mPhoneNumberPickerActionListener);
             mSearchFragment.setQuickContactEnabled(true);
+            mSearchFragment.setDarkTheme(true);
             final FragmentTransaction transaction = getFragmentManager().beginTransaction();
             if (mInSearchUi) {
                 transaction.show(mSearchFragment);
@@ -496,11 +497,8 @@
     protected void onPause() {
         super.onPause();
 
-        final SharedPreferences.Editor editor =
-                getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE).edit();
-        editor.putInt(PREF_LAST_MANUALLY_SELECTED_TAB, mLastManuallySelectedFragment);
-
-        editor.apply();
+        mPrefs.edit().putInt(PREF_LAST_MANUALLY_SELECTED_TAB, mLastManuallySelectedFragment)
+                .apply();
     }
 
     private void fixIntent(Intent intent) {
diff --git a/src/com/android/contacts/calllog/CallLogAdapter.java b/src/com/android/contacts/calllog/CallLogAdapter.java
index 4223146..0bbf53c 100644
--- a/src/com/android/contacts/calllog/CallLogAdapter.java
+++ b/src/com/android/contacts/calllog/CallLogAdapter.java
@@ -776,7 +776,7 @@
 
     private void setPhoto(CallLogListItemViews views, long photoId, Uri contactUri) {
         views.quickContactView.assignContactUri(contactUri);
-        mContactPhotoManager.loadPhoto(views.quickContactView, photoId);
+        mContactPhotoManager.loadPhoto(views.quickContactView, photoId, false, true);
     }
 
     /**
diff --git a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
index f6690d6..bdcd6b0 100644
--- a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
+++ b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
@@ -200,7 +200,7 @@
         }
         byte[] photo = contactData.getPhotoBinaryData();
         Bitmap bitmap = photo != null ? BitmapFactory.decodeByteArray(photo, 0, photo.length)
-                : ContactBadgeUtil.loadPlaceholderPhoto(context);
+                : ContactBadgeUtil.loadDefaultAvatarPhoto(context, true, false);
         boolean fadeIn = contactData.isDirectoryEntry();
         if (photoView.getDrawable() == null && fadeIn) {
             AlphaAnimation animation = new AlphaAnimation(0, 1);
@@ -249,7 +249,7 @@
         setDataOrHideIfNone(snippet, statusView);
         if (photoUri != null) {
             ContactPhotoManager.getInstance(context).loadPhoto(
-                    statusPhotoView, Uri.parse(photoUri));
+                    statusPhotoView, Uri.parse(photoUri), true, false);
             statusPhotoView.setVisibility(View.VISIBLE);
         } else {
             statusPhotoView.setVisibility(View.GONE);
@@ -338,7 +338,8 @@
             pushLayerView.setClickable(false);
             pushLayerView.setEnabled(false);
         }
-        contactPhotoManager.loadPhoto(imageView, Uri.parse(streamItemPhoto.getPhotoUri()));
+        contactPhotoManager.loadPhoto(imageView, Uri.parse(streamItemPhoto.getPhotoUri()), true,
+                false);
     }
 
     @VisibleForTesting
diff --git a/src/com/android/contacts/editor/AggregationSuggestionView.java b/src/com/android/contacts/editor/AggregationSuggestionView.java
index df90cff..996dbc4 100644
--- a/src/com/android/contacts/editor/AggregationSuggestionView.java
+++ b/src/com/android/contacts/editor/AggregationSuggestionView.java
@@ -86,7 +86,7 @@
             photo.setImageBitmap(BitmapFactory.decodeByteArray(
                     suggestion.photo, 0, suggestion.photo.length));
         } else {
-            photo.setImageResource(R.drawable.ic_contact_picture);
+            photo.setImageResource(R.drawable.ic_contact_picture_holo_light);
         }
 
         TextView name = (TextView) findViewById(R.id.aggregation_suggestion_name);
diff --git a/src/com/android/contacts/editor/PhotoEditorView.java b/src/com/android/contacts/editor/PhotoEditorView.java
index b9b8c2c..086b07f 100644
--- a/src/com/android/contacts/editor/PhotoEditorView.java
+++ b/src/com/android/contacts/editor/PhotoEditorView.java
@@ -162,7 +162,7 @@
 
     protected void resetDefault() {
         // Invalid photo, show default "add photo" place-holder
-        mPhotoImageView.setImageResource(R.drawable.ic_contact_picture);
+        mPhotoImageView.setImageResource(R.drawable.ic_contact_picture_holo_light);
         mFrameView.setEnabled(!mReadOnly && isEnabled());
         mHasSetPhoto = false;
         mEntry.setFromTemplate(true);
diff --git a/src/com/android/contacts/group/GroupEditorFragment.java b/src/com/android/contacts/group/GroupEditorFragment.java
index 96e0c8a..99e6b48 100644
--- a/src/com/android/contacts/group/GroupEditorFragment.java
+++ b/src/com/android/contacts/group/GroupEditorFragment.java
@@ -971,7 +971,7 @@
                 });
             }
 
-            mPhotoManager.loadPhoto(badge, member.getPhotoUri());
+            mPhotoManager.loadPhoto(badge, member.getPhotoUri(), false, false);
             return result;
         }
 
diff --git a/src/com/android/contacts/group/SuggestedMemberListAdapter.java b/src/com/android/contacts/group/SuggestedMemberListAdapter.java
index 623b5a2..08401bf 100644
--- a/src/com/android/contacts/group/SuggestedMemberListAdapter.java
+++ b/src/com/android/contacts/group/SuggestedMemberListAdapter.java
@@ -143,7 +143,7 @@
         }
         byte[] byteArray = member.getPhotoByteArray();
         if (byteArray == null) {
-            icon.setImageResource(R.drawable.ic_contact_picture);
+            icon.setImageResource(R.drawable.ic_contact_picture_holo_light);
         } else {
             Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
             icon.setImageBitmap(bitmap);
diff --git a/src/com/android/contacts/list/ContactEntryListAdapter.java b/src/com/android/contacts/list/ContactEntryListAdapter.java
index 9b968f7..9c36f05 100644
--- a/src/com/android/contacts/list/ContactEntryListAdapter.java
+++ b/src/com/android/contacts/list/ContactEntryListAdapter.java
@@ -90,6 +90,7 @@
 
     private ContactListFilter mFilter;
     private String mContactsCount = "";
+    private boolean mDarkTheme = false;
 
     public ContactEntryListAdapter(Context context) {
         super(context);
@@ -306,6 +307,10 @@
         return mProfileExists;
     }
 
+    public void setDarkTheme(boolean value) {
+        mDarkTheme = value;
+    }
+
     public void configureDirectoryLoader(DirectoryListLoader loader) {
         loader.setDirectorySearchMode(mDirectorySearchMode);
         loader.setLocalInvisibleDirectoryEnabled(LOCAL_INVISIBLE_DIRECTORY_ENABLED);
@@ -607,7 +612,7 @@
         QuickContactBadge quickContact = view.getQuickContact();
         quickContact.assignContactUri(
                 getContactUri(partitionIndex, cursor, contactIdColumn, lookUpKeyColumn));
-        getPhotoLoader().loadPhoto(quickContact, photoId);
+        getPhotoLoader().loadPhoto(quickContact, photoId, false, mDarkTheme);
     }
 
     protected Uri getContactUri(int partitionIndex, Cursor cursor,
diff --git a/src/com/android/contacts/list/ContactEntryListFragment.java b/src/com/android/contacts/list/ContactEntryListFragment.java
index e361a19..91c582c 100644
--- a/src/com/android/contacts/list/ContactEntryListFragment.java
+++ b/src/com/android/contacts/list/ContactEntryListFragment.java
@@ -19,7 +19,6 @@
 import com.android.common.widget.CompositeCursorAdapter.Partition;
 import com.android.contacts.ContactListEmptyView;
 import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.ContactsSearchManager;
 import com.android.contacts.R;
 import com.android.contacts.preference.ContactsPreferences;
 import com.android.contacts.widget.ContextMenuAdapter;
@@ -86,6 +85,7 @@
     private static final String KEY_DIRECTORY_SEARCH_MODE = "directorySearchMode";
     private static final String KEY_SELECTION_VISIBLE = "selectionVisible";
     private static final String KEY_REQUEST = "request";
+    private static final String KEY_DARK_THEME = "darkTheme";
     private static final String KEY_LEGACY_COMPATIBILITY = "legacyCompatibility";
     private static final String KEY_DIRECTORY_RESULT_LIMIT = "directoryResultLimit";
 
@@ -134,6 +134,8 @@
 
     private boolean mForceLoad;
 
+    private boolean mDarkTheme;
+
     protected boolean mUserProfileExists;
 
     private static final int STATUS_NOT_LOADED = 0;
@@ -161,7 +163,6 @@
         }
     };
 
-
     protected abstract View inflateView(LayoutInflater inflater, ViewGroup container);
     protected abstract T createListAdapter();
 
@@ -249,6 +250,7 @@
         outState.putString(KEY_QUERY_STRING, mQueryString);
         outState.putInt(KEY_DIRECTORY_RESULT_LIMIT, mDirectoryResultLimit);
         outState.putParcelable(KEY_REQUEST, mRequest);
+        outState.putBoolean(KEY_DARK_THEME, mDarkTheme);
 
         if (mListView != null) {
             mListState = mListView.onSaveInstanceState();
@@ -281,6 +283,7 @@
         mQueryString = savedState.getString(KEY_QUERY_STRING);
         mDirectoryResultLimit = savedState.getInt(KEY_DIRECTORY_RESULT_LIMIT);
         mRequest = savedState.getParcelable(KEY_REQUEST);
+        mDarkTheme = savedState.getBoolean(KEY_DARK_THEME);
 
         // Retrieve list state. This will be applied in onLoadFinished
         mListState = savedState.getParcelable(KEY_LIST_STATE);
@@ -812,6 +815,7 @@
         mAdapter.setSectionHeaderDisplayEnabled(mSectionHeaderDisplayEnabled);
         mAdapter.setSelectionVisible(mSelectionVisible);
         mAdapter.setDirectoryResultLimit(mDirectoryResultLimit);
+        mAdapter.setDarkTheme(mDarkTheme);
     }
 
     @Override
@@ -920,6 +924,11 @@
         return telephonyManager.hasIccCard();
     }
 
+    public void setDarkTheme(boolean value) {
+        mDarkTheme = value;
+        if (mAdapter != null) mAdapter.setDarkTheme(value);
+    }
+
     /**
      * Processes a result returned by the contact picker.
      */
diff --git a/src/com/android/contacts/list/ContactListAdapter.java b/src/com/android/contacts/list/ContactListAdapter.java
index 0553909..6eb9423 100644
--- a/src/com/android/contacts/list/ContactListAdapter.java
+++ b/src/com/android/contacts/list/ContactListAdapter.java
@@ -255,11 +255,11 @@
         }
 
         if (photoId != 0) {
-            getPhotoLoader().loadPhoto(view.getPhotoView(), photoId);
+            getPhotoLoader().loadPhoto(view.getPhotoView(), photoId, false, false);
         } else {
             final String photoUriString = cursor.getString(CONTACT_PHOTO_URI_COLUMN_INDEX);
             final Uri photoUri = photoUriString == null ? null : Uri.parse(photoUriString);
-            getPhotoLoader().loadPhoto(view.getPhotoView(), photoUri);
+            getPhotoLoader().loadPhoto(view.getPhotoView(), photoUri, false, false);
         }
     }
 
diff --git a/src/com/android/contacts/list/ContactListItemView.java b/src/com/android/contacts/list/ContactListItemView.java
index f47560b..70493c5 100644
--- a/src/com/android/contacts/list/ContactListItemView.java
+++ b/src/com/android/contacts/list/ContactListItemView.java
@@ -48,11 +48,6 @@
 import android.widget.QuickContactBadge;
 import android.widget.TextView;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
 /**
  * A custom view for an item in the contact list.
  * The view contains the contact's photo, a set of text views (for name, status, etc...) and
diff --git a/src/com/android/contacts/list/ContactTileDarkFrequentView.java b/src/com/android/contacts/list/ContactTileDarkFrequentView.java
new file mode 100644
index 0000000..78f45bd
--- /dev/null
+++ b/src/com/android/contacts/list/ContactTileDarkFrequentView.java
@@ -0,0 +1,33 @@
+/*
+ * 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.list;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+/**
+ * A dark version of the {@link ContactTileView} (This class is needed to load the proper avatar)
+ */
+public class ContactTileDarkFrequentView extends ContactTileView {
+    public ContactTileDarkFrequentView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected boolean isDarkTheme() {
+        return true;
+    }
+}
diff --git a/src/com/android/contacts/list/ContactTileSecondaryTargetView.java b/src/com/android/contacts/list/ContactTileSecondaryTargetView.java
index 073ac29..c4ea212 100644
--- a/src/com/android/contacts/list/ContactTileSecondaryTargetView.java
+++ b/src/com/android/contacts/list/ContactTileSecondaryTargetView.java
@@ -50,4 +50,9 @@
             }
         });
     }
+
+    @Override
+    protected boolean isDarkTheme() {
+        return true;
+    }
 }
diff --git a/src/com/android/contacts/list/ContactTileStarredView.java b/src/com/android/contacts/list/ContactTileStarredView.java
index c017731..3be6bf2 100644
--- a/src/com/android/contacts/list/ContactTileStarredView.java
+++ b/src/com/android/contacts/list/ContactTileStarredView.java
@@ -22,9 +22,6 @@
  * A {@link ContactTileStarredView} displays the contact's picture overlayed with their name
  * in a square.  The actual dimensions are set by
  * {@link com.android.contacts.list.ContactTileAdapter.ContactTileRow}.
- *
- * TODO Just remove this class.  We probably don't need {@link ContactTileSecondaryTargetView}
- * either.  (We can probably put the functionality to {@link ContactTileView})
  */
 public class ContactTileStarredView extends ContactTileView {
     private final static String TAG = ContactTileStarredView.class.getSimpleName();
@@ -32,4 +29,9 @@
     public ContactTileStarredView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
+
+    @Override
+    protected boolean isDefaultIconHires() {
+        return true;
+    }
 }
diff --git a/src/com/android/contacts/list/ContactTileView.java b/src/com/android/contacts/list/ContactTileView.java
index 137f6e7..0b90c44 100644
--- a/src/com/android/contacts/list/ContactTileView.java
+++ b/src/com/android/contacts/list/ContactTileView.java
@@ -118,19 +118,27 @@
 
             if (mPhotoManager != null) {
                 if (mPhoto != null) {
-                    mPhotoManager.loadPhoto(mPhoto, entry.photoUri);
+                    mPhotoManager.loadPhoto(mPhoto, entry.photoUri, isDefaultIconHires(),
+                            isDarkTheme());
 
                     if (mQuickContact != null) {
                         mQuickContact.assignContactUri(mLookupUri);
                     }
                 } else if (mQuickContact != null) {
                     mQuickContact.assignContactUri(mLookupUri);
-                    mPhotoManager.loadPhoto(mQuickContact, entry.photoUri);
+                    mPhotoManager.loadPhoto(mQuickContact, entry.photoUri, isDefaultIconHires(),
+                            isDarkTheme());
                 }
 
             } else {
                 Log.w(TAG, "contactPhotoManager not set");
             }
+
+            if (mPushState != null) {
+                mPushState.setContentDescription(entry.name);
+            } else if (mQuickContact != null) {
+                mQuickContact.setContentDescription(entry.name);
+            }
         } else {
             setVisibility(View.INVISIBLE);
         }
@@ -148,6 +156,14 @@
         return mLookupUri;
     }
 
+    protected boolean isDefaultIconHires() {
+        return false;
+    }
+
+    protected boolean isDarkTheme() {
+        return false;
+    }
+
     public interface Listener {
         void onClick(ContactTileView contactTileView);
     }
diff --git a/src/com/android/contacts/list/EmailAddressListAdapter.java b/src/com/android/contacts/list/EmailAddressListAdapter.java
index 5f96297..52daaa0 100644
--- a/src/com/android/contacts/list/EmailAddressListAdapter.java
+++ b/src/com/android/contacts/list/EmailAddressListAdapter.java
@@ -175,7 +175,7 @@
             photoId = cursor.getLong(EMAIL_PHOTO_ID_COLUMN_INDEX);
         }
 
-        getPhotoLoader().loadPhoto(view.getPhotoView(), photoId);
+        getPhotoLoader().loadPhoto(view.getPhotoView(), photoId, false, false);
     }
 //
 //    protected void bindSearchSnippet(final ContactListItemView view, Cursor cursor) {
diff --git a/src/com/android/contacts/list/PhoneNumberListAdapter.java b/src/com/android/contacts/list/PhoneNumberListAdapter.java
index a86e082..5c12dd6 100644
--- a/src/com/android/contacts/list/PhoneNumberListAdapter.java
+++ b/src/com/android/contacts/list/PhoneNumberListAdapter.java
@@ -313,6 +313,6 @@
             photoId = cursor.getLong(PHONE_PHOTO_ID_COLUMN_INDEX);
         }
 
-        getPhotoLoader().loadPhoto(view.getPhotoView(), photoId);
+        getPhotoLoader().loadPhoto(view.getPhotoView(), photoId, false, false);
     }
 }
diff --git a/src/com/android/contacts/list/PhoneNumberPickerFragment.java b/src/com/android/contacts/list/PhoneNumberPickerFragment.java
index 88e5ecf..938d43a 100644
--- a/src/com/android/contacts/list/PhoneNumberPickerFragment.java
+++ b/src/com/android/contacts/list/PhoneNumberPickerFragment.java
@@ -15,7 +15,6 @@
  */
 package com.android.contacts.list;
 
-import com.android.contacts.ContactsSearchManager;
 import com.android.contacts.R;
 import com.android.contacts.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
 
diff --git a/src/com/android/contacts/list/PostalAddressListAdapter.java b/src/com/android/contacts/list/PostalAddressListAdapter.java
index c9da281..7e58a8e 100644
--- a/src/com/android/contacts/list/PostalAddressListAdapter.java
+++ b/src/com/android/contacts/list/PostalAddressListAdapter.java
@@ -164,7 +164,7 @@
             photoId = cursor.getLong(POSTAL_PHOTO_ID_COLUMN_INDEX);
         }
 
-        getPhotoLoader().loadPhoto(view.getPhotoView(), photoId);
+        getPhotoLoader().loadPhoto(view.getPhotoView(), photoId, false, false);
     }
 //
 //    protected void bindSearchSnippet(final ContactListItemView view, Cursor cursor) {
diff --git a/src/com/android/contacts/list/ShortcutIntentBuilder.java b/src/com/android/contacts/list/ShortcutIntentBuilder.java
index 3aa0b55..886732c 100644
--- a/src/com/android/contacts/list/ShortcutIntentBuilder.java
+++ b/src/com/android/contacts/list/ShortcutIntentBuilder.java
@@ -224,7 +224,7 @@
             bitmap = BitmapFactory.decodeByteArray(bitmapData, 0, bitmapData.length, null);
         } else {
             bitmap = ((BitmapDrawable) mContext.getResources().getDrawableForDensity(
-                    R.drawable.ic_contact_picture, mIconDensity)).getBitmap();
+                    R.drawable.ic_contact_picture_holo_light, mIconDensity)).getBitmap();
         }
 
         Intent shortcutIntent;
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 472f701..fbca129 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -17,11 +17,11 @@
 package com.android.contacts.quickcontact;
 
 import com.android.contacts.Collapser;
+import com.android.contacts.ContactPhotoManager;
 import com.android.contacts.ContactPresenceIconUtil;
 import com.android.contacts.R;
 import com.android.contacts.model.AccountTypeManager;
 import com.android.contacts.model.DataKind;
-import com.android.contacts.util.ContactBadgeUtil;
 import com.android.contacts.util.DataStatus;
 import com.android.contacts.util.NotifyingAsyncQueryHandler;
 import com.android.contacts.util.NotifyingAsyncQueryHandler.AsyncQueryListener;
@@ -491,8 +491,11 @@
 
         if (photoView != null) {
             // Place photo when discovered in data, otherwise show generic avatar
-            photoView.setImageBitmap(photoBitmap != null ? photoBitmap
-                    : ContactBadgeUtil.loadPlaceholderPhoto(context));
+            if (photoBitmap != null) {
+                photoView.setImageBitmap(photoBitmap);
+            } else {
+                photoView.setImageResource(ContactPhotoManager.getDefaultAvatarResId(true, false));
+            }
         }
 
         // TODO: Bring this back once we have a design
diff --git a/src/com/android/contacts/socialwidget/SocialWidgetProvider.java b/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
index 9d064a5..9f7e18f 100644
--- a/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
+++ b/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
@@ -136,12 +136,12 @@
         if (contactData.isError() || contactData == ContactLoader.Result.NOT_FOUND) {
             setDisplayNameAndSnippet(context, views,
                     context.getString(R.string.invalidContactMessage), null, null, null);
-            setPhoto(views, ContactBadgeUtil.loadPlaceholderPhoto(context));
+            setPhoto(views, ContactBadgeUtil.loadDefaultAvatarPhoto(context, false, false));
         } else {
             byte[] photo = contactData.getPhotoBinaryData();
             setPhoto(views, photo != null
                     ? BitmapFactory.decodeByteArray(photo, 0, photo.length)
-                            : ContactBadgeUtil.loadPlaceholderPhoto(context));
+                            : ContactBadgeUtil.loadDefaultAvatarPhoto(context, false, false));
 
             // TODO: Rotate between all the stream items?
 
diff --git a/src/com/android/contacts/socialwidget/SocialWidgetSettings.java b/src/com/android/contacts/socialwidget/SocialWidgetSettings.java
index 18b5041..45a7dfb 100644
--- a/src/com/android/contacts/socialwidget/SocialWidgetSettings.java
+++ b/src/com/android/contacts/socialwidget/SocialWidgetSettings.java
@@ -20,54 +20,96 @@
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.Editor;
 import android.net.Uri;
+import android.preference.PreferenceManager;
 import android.util.Log;
 
 public class SocialWidgetSettings {
     private static final String TAG = "SocialWidgetSettings";
 
-    private static final String PREFS_NAME = "WidgetSettings";
+    // To migrate from earlier versions...
+    private static final String LEGACY_PREFS_NAME = "WidgetSettings";
+
+    // Prefix to use for all preferences used by this class.
+    private static final String PREFERENCES_PREFIX = "SocialWidgetSettings_";
+
     private static final String CONTACT_URI_PREFIX = "CONTACT_URI_";
 
+    private static final String KEY_MIGRATED = PREFERENCES_PREFIX + "settings_migrated";
+
     private static final SocialWidgetSettings sInstance = new SocialWidgetSettings();
 
     public static SocialWidgetSettings getInstance() {
         return sInstance;
     }
 
-    private final String getSettingsString(int widgetId) {
-        return CONTACT_URI_PREFIX + Integer.toString(widgetId);
+    private final String getPreferenceKey(int widgetId) {
+        return PREFERENCES_PREFIX + CONTACT_URI_PREFIX + Integer.toString(widgetId);
     }
 
     public void remove(Context context, int[] widgetIds) {
-        final SharedPreferences settings =
-            context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
+        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
         final Editor editor = settings.edit();
         for (int widgetId : widgetIds) {
-            Log.d(TAG, "remove(" + widgetId + ")");
-            editor.remove(getSettingsString(widgetId));
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "remove(" + widgetId + ")");
+            }
+            editor.remove(getPreferenceKey(widgetId));
         }
         editor.apply();
     }
 
     public Uri getContactUri(Context context, int widgetId) {
-        final SharedPreferences settings =
-                context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
-        final String resultString = settings.getString(getSettingsString(widgetId), null);
+        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
+
+        ensureMigrated(context, settings);
+
+        final String resultString = settings.getString(getPreferenceKey(widgetId), null);
         final Uri result = resultString == null ? null : Uri.parse(resultString);
-        Log.d(TAG, "getContactUri(" + widgetId + ") --> " + result);
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "getContactUri(" + widgetId + ") --> " + result);
+        }
         return result;
     }
 
     public void setContactUri(Context context, int widgetId, Uri contactLookupUri) {
-        Log.d(TAG, "setContactUri(" + widgetId + ", " + contactLookupUri + ")");
-        final SharedPreferences settings =
-                context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "setContactUri(" + widgetId + ", " + contactLookupUri + ")");
+        }
+        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
         final Editor editor = settings.edit();
         if (contactLookupUri == null) {
-            editor.remove(getSettingsString(widgetId));
+            editor.remove(getPreferenceKey(widgetId));
         } else {
-            editor.putString(getSettingsString(widgetId), contactLookupUri.toString());
+            editor.putString(getPreferenceKey(widgetId), contactLookupUri.toString());
         }
         editor.apply();
     }
+
+    private void ensureMigrated(Context context, SharedPreferences settings) {
+        if (settings.getBoolean(KEY_MIGRATED, false)) {
+            return; // Migrated already
+        }
+
+        Log.i(TAG, "Migrating widget settings...");
+
+        // Old preferences only had the "CONTACT_URI_" prefix.
+        // New preferences have the "SocialWidgetSettings_CONTACT_URI_" prefix.
+        // So just copy all the entries with adding "SocialWidgetSettings_" to their key names.
+
+        final SharedPreferences.Editor editor = settings.edit();
+
+        final SharedPreferences legacySettings =
+            context.getSharedPreferences(LEGACY_PREFS_NAME, Context.MODE_PRIVATE);
+        for (String key : legacySettings.getAll().keySet()) {
+            final String value = legacySettings.getString(key, null);
+            if (value == null) continue; // Just in case.
+
+            Log.i(TAG, "Found: " + key + ": " + value);
+
+            editor.putString(PREFERENCES_PREFIX + key, value);
+        }
+
+        editor.apply();
+        settings.edit().putBoolean(KEY_MIGRATED, true).apply();
+    }
 }
diff --git a/src/com/android/contacts/util/ContactBadgeUtil.java b/src/com/android/contacts/util/ContactBadgeUtil.java
index a89177a..de90c40 100644
--- a/src/com/android/contacts/util/ContactBadgeUtil.java
+++ b/src/com/android/contacts/util/ContactBadgeUtil.java
@@ -16,6 +16,7 @@
 
 package com.android.contacts.util;
 
+import com.android.contacts.ContactPhotoManager;
 import com.android.contacts.R;
 
 import android.content.Context;
@@ -106,7 +107,8 @@
         return attribution;
     }
 
-    public static Bitmap loadPlaceholderPhoto(Context context) {
-        return BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_contact_picture);
+    public static Bitmap loadDefaultAvatarPhoto(Context context, boolean hires, boolean darkTheme) {
+        return BitmapFactory.decodeResource(context.getResources(),
+                ContactPhotoManager.getDefaultAvatarResId(hires, darkTheme));
     }
 }
diff --git a/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java b/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java
index 416b841..a98b365 100644
--- a/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java
+++ b/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java
@@ -27,13 +27,13 @@
  */
 public class MockContactPhotoManager extends ContactPhotoManager {
     @Override
-    public void loadPhoto(ImageView view, long photoId) {
-        view.setImageResource(mDefaultResourceId);
+    public void loadPhoto(ImageView view, long photoId, boolean hires, boolean darkTheme) {
+        view.setImageResource(getDefaultAvatarResId(hires, darkTheme));
     }
 
     @Override
-    public void loadPhoto(ImageView view, Uri photoUri) {
-        view.setImageResource(mDefaultResourceId);
+    public void loadPhoto(ImageView view, Uri photoUri, boolean hires, boolean darkTheme) {
+        view.setImageResource(getDefaultAvatarResId(hires, darkTheme));
     }
 
     @Override