Add contact picture to the call log.

This commit adds contact pictures to the call log. Since the photo id
for contacts is not currently cached, photos will be reloaded each time
the call log is shown.

Change-Id: I6839399a8db97ab9dfa5f464afbabe86e513d1f9
diff --git a/res/layout/call_log_contact_photo.xml b/res/layout/call_log_contact_photo.xml
new file mode 100644
index 0000000..b8262ad
--- /dev/null
+++ b/res/layout/call_log_contact_photo.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <ImageView
+        android:id="@+id/contact_photo"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentLeft="true"
+    />
+</merge>
diff --git a/res/layout/call_log_list_group_item.xml b/res/layout/call_log_list_group_item.xml
index d1bd165..c922540 100644
--- a/res/layout/call_log_list_group_item.xml
+++ b/res/layout/call_log_list_group_item.xml
@@ -20,6 +20,7 @@
     android:paddingLeft="7dip"
 >
 
+    <include layout="@layout/call_log_contact_photo"/>
     <include layout="@layout/call_log_action_group"/>
 
     <TextView android:id="@+id/date"
@@ -39,7 +40,7 @@
         android:layout_height="wrap_content"
         android:layout_alignParentLeft="true"
         android:layout_alignParentBottom="true"
-        android:layout_marginLeft="36dip"
+        android:layout_marginLeft="86dip"
         android:layout_marginRight="5dip"
         android:layout_alignBaseline="@id/date"
 
@@ -84,7 +85,7 @@
         android:layout_toLeftOf="@+id/groupSize"
         android:layout_above="@id/date"
         android:layout_alignWithParentIfMissing="true"
-        android:layout_marginLeft="36dip"
+        android:layout_marginLeft="86dip"
         android:layout_marginBottom="-10dip"
 
         android:textAppearance="?android:attr/textAppearanceLarge"
diff --git a/res/layout/call_log_list_item.xml b/res/layout/call_log_list_item.xml
index 10e09a4..88a1ba1 100644
--- a/res/layout/call_log_list_item.xml
+++ b/res/layout/call_log_list_item.xml
@@ -20,6 +20,7 @@
     android:paddingLeft="7dip"
 >
 
+    <include layout="@layout/call_log_contact_photo"/>
     <include layout="@layout/call_log_action_call"/>
     <include layout="@layout/call_log_list_item_layout"/>
 
diff --git a/res/layout/call_log_list_item_layout.xml b/res/layout/call_log_list_item_layout.xml
index 8096ee6..2128a79 100644
--- a/res/layout/call_log_list_item_layout.xml
+++ b/res/layout/call_log_list_item_layout.xml
@@ -19,9 +19,9 @@
     <ImageView android:id="@+id/call_type_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_alignParentTop="true"
+        android:layout_alignParentBottom="true"
         android:layout_alignParentLeft="true"
-        android:layout_marginLeft="4dip"
+        android:layout_marginLeft="54dip"
     />
 
     <TextView android:id="@+id/date"
@@ -41,7 +41,7 @@
         android:layout_height="wrap_content"
         android:layout_alignParentLeft="true"
         android:layout_alignParentBottom="true"
-        android:layout_marginLeft="36dip"
+        android:layout_marginLeft="86dip"
         android:layout_marginRight="5dip"
         android:layout_alignBaseline="@id/date"
 
@@ -72,7 +72,7 @@
         android:layout_toLeftOf="@id/divider"
         android:layout_above="@id/date"
         android:layout_alignWithParentIfMissing="true"
-        android:layout_marginLeft="36dip"
+        android:layout_marginLeft="86dip"
         android:layout_marginBottom="-10dip"
 
         android:textAppearance="?android:attr/textAppearanceLarge"
diff --git a/src/com/android/contacts/calllog/CallLogFragment.java b/src/com/android/contacts/calllog/CallLogFragment.java
index 79e9ae5..eff5c41 100644
--- a/src/com/android/contacts/calllog/CallLogFragment.java
+++ b/src/com/android/contacts/calllog/CallLogFragment.java
@@ -18,6 +18,7 @@
 
 import com.android.common.widget.GroupingListAdapter;
 import com.android.contacts.CallDetailActivity;
+import com.android.contacts.ContactPhotoManager;
 import com.android.contacts.ContactsUtils;
 import com.android.contacts.R;
 import com.android.internal.telephony.CallerInfo;
@@ -111,7 +112,8 @@
                 PhoneLookup.TYPE,
                 PhoneLookup.LABEL,
                 PhoneLookup.NUMBER,
-                PhoneLookup.NORMALIZED_NUMBER};
+                PhoneLookup.NORMALIZED_NUMBER,
+                PhoneLookup.PHOTO_ID};
 
         public static final int PERSON_ID = 0;
         public static final int NAME = 1;
@@ -119,6 +121,7 @@
         public static final int LABEL = 3;
         public static final int MATCHED_NUMBER = 4;
         public static final int NORMALIZED_NUMBER = 5;
+        public static final int PHOTO_ID = 6;
     }
 
     private static final class MenuItems {
@@ -146,6 +149,7 @@
         public String number;
         public String formattedNumber;
         public String normalizedNumber;
+        public long photoId;
 
         public static ContactInfo EMPTY = new ContactInfo();
     }
@@ -165,6 +169,8 @@
          * entries.
          */
         public TextView groupSize;
+        /** The contact photo for the contact. Only present for group and stand alone entries. */
+        public ImageView photoView;
     }
 
     public static final class CallerInfoQuery {
@@ -173,6 +179,7 @@
         public String name;
         public int numberType;
         public String numberLabel;
+        public long photoId;
     }
 
     /** Adapter class to fill in data for the Call Log */
@@ -197,6 +204,8 @@
          */
         private CharArrayBuffer mBuffer1 = new CharArrayBuffer(128);
         private CharArrayBuffer mBuffer2 = new CharArrayBuffer(128);
+        /** Helper to set up contact photos. */
+        private final ContactPhotoManager mContactPhotoManager;
 
         @Override
         public void onClick(View view) {
@@ -251,6 +260,8 @@
                     R.drawable.ic_call_log_list_outgoing_call);
             mDrawableMissed = getResources().getDrawable(
                     R.drawable.ic_call_log_list_missed_call);
+
+            mContactPhotoManager = ContactPhotoManager.getInstance(getActivity());
         }
 
         /**
@@ -311,7 +322,8 @@
             // Check if they are different. If not, don't update.
             if (TextUtils.equals(ciq.name, ci.name)
                     && TextUtils.equals(ciq.numberLabel, ci.label)
-                    && ciq.numberType == ci.type) {
+                    && ciq.numberType == ci.type
+                    && ciq.photoId == ci.photoId) {
                 return;
             }
             ContentValues values = new ContentValues(3);
@@ -332,13 +344,14 @@
         }
 
         private void enqueueRequest(String number, int position,
-                String name, int numberType, String numberLabel) {
+                String name, int numberType, String numberLabel, long photoId) {
             CallerInfoQuery ciq = new CallerInfoQuery();
             ciq.number = number;
             ciq.position = position;
             ciq.name = name;
             ciq.numberType = numberType;
             ciq.numberLabel = numberLabel;
+            ciq.photoId = photoId;
             synchronized (mRequests) {
                 mRequests.add(ciq);
                 mRequests.notifyAll();
@@ -414,6 +427,8 @@
                             info.number = dataTableCursor.getString(
                                     dataTableCursor.getColumnIndex(Data.DATA1));
                             info.normalizedNumber = null;  // meaningless for SIP addresses
+                            info.photoId = dataTableCursor.getLong(
+                                    dataTableCursor.getColumnIndex(Data.PHOTO_ID));
 
                             infoUpdated = true;
                         }
@@ -438,6 +453,7 @@
                                     .getString(PhoneQuery.MATCHED_NUMBER);
                             info.normalizedNumber = phonesCursor
                                     .getString(PhoneQuery.NORMALIZED_NUMBER);
+                            info.photoId = phonesCursor.getLong(PhoneQuery.PHOTO_ID);
 
                             infoUpdated = true;
                         }
@@ -624,6 +640,7 @@
             }
             views.groupIndicator = (ImageView) view.findViewById(R.id.groupIndicator);
             views.groupSize = (TextView) view.findViewById(R.id.groupSize);
+            views.photoView = (ImageView) view.findViewById(R.id.contact_photo);
             view.setTag(views);
         }
 
@@ -649,7 +666,7 @@
                 info = ContactInfo.EMPTY;
                 mContactInfo.put(number, info);
                 enqueueRequest(number, c.getPosition(),
-                        callerName, callerNumberType, callerNumberLabel);
+                        callerName, callerNumberType, callerNumberLabel, 0L);
             } else if (info != ContactInfo.EMPTY) { // Has been queried
                 // Check if any data is different from the data cached in the
                 // calls db. If so, queue the request so that we can update
@@ -659,7 +676,7 @@
                         || !TextUtils.equals(info.label, callerNumberLabel)) {
                     // Something is amiss, so sync up.
                     enqueueRequest(number, c.getPosition(),
-                            callerName, callerNumberType, callerNumberLabel);
+                            callerName, callerNumberType, callerNumberLabel, info.photoId);
                 }
 
                 // Format and cache phone number for found contact
@@ -673,6 +690,7 @@
             String name = info.name;
             int ntype = info.type;
             String label = info.label;
+            long photoId = info.photoId;
             // If there's no name cached in our hashmap, but there's one in the
             // calls db, use the one in the calls db. Otherwise the name in our
             // hashmap is more recent, so it has precedence.
@@ -759,6 +777,10 @@
                 views.labelView.setVisibility(View.GONE);
             }
 
+            if (views.photoView != null) {
+                mContactPhotoManager.loadPhoto(views.photoView, photoId);
+            }
+
             long date = c.getLong(CallLogQuery.DATE);
 
             // Set the date/time field by mixing relative and absolute times.