Add Caller information to missed call notifications.

Includes moving ContactsAsyncHelper from services/Telephony to here.
This was a wholesale copy with only changes to:
1) Update logging to use Telecomm's implementation
2) Removal of ImageTracker inner class (was causing linking
   errors and was totally unused in both telecomm and
   services/Telephony).

Bug: 15313021
Change-Id: I4e3ce52ce1c31eb7b684d8e404fdcff4bb7db7ba
diff --git a/src/com/android/telecomm/Call.java b/src/com/android/telecomm/Call.java
index 5eb2f97..699a3e2 100644
--- a/src/com/android/telecomm/Call.java
+++ b/src/com/android/telecomm/Call.java
@@ -16,9 +16,13 @@
 
 package com.android.telecomm;
 
+import android.content.ContentUris;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
+import android.provider.ContactsContract.Contacts;
 import android.telecomm.CallInfo;
 import android.telecomm.CallServiceDescriptor;
 import android.telecomm.CallState;
@@ -31,6 +35,8 @@
 import com.android.internal.telephony.CallerInfo;
 import com.android.internal.telephony.CallerInfoAsyncQuery;
 import com.android.internal.telephony.CallerInfoAsyncQuery.OnQueryCompleteListener;
+
+import com.android.telecomm.ContactsAsyncHelper.OnImageLoadCompleteListener;
 import com.google.android.collect.Sets;
 import com.google.common.base.Preconditions;
 
@@ -55,15 +61,27 @@
     }
 
     private static final OnQueryCompleteListener sCallerInfoQueryListener =
-        new OnQueryCompleteListener() {
-            /** ${inheritDoc} */
-            @Override
-            public void onQueryComplete(int token, Object cookie, CallerInfo callerInfo) {
-                if (cookie != null) {
-                    ((Call) cookie).setCallerInfo(callerInfo, token);
+            new OnQueryCompleteListener() {
+                /** ${inheritDoc} */
+                @Override
+                public void onQueryComplete(int token, Object cookie, CallerInfo callerInfo) {
+                    if (cookie != null) {
+                        ((Call) cookie).setCallerInfo(callerInfo, token);
+                    }
                 }
-            }
-        };
+            };
+
+    private static final OnImageLoadCompleteListener sPhotoLoadListener =
+            new OnImageLoadCompleteListener() {
+                /** ${inheritDoc} */
+                @Override
+                public void onImageLoadComplete(
+                        int token, Drawable photo, Bitmap photoIcon, Object cookie) {
+                    if (cookie != null) {
+                        ((Call) cookie).setPhoto(photo, photoIcon, token);
+                    }
+                }
+            };
 
     /** True if this is an incoming call. */
     private final boolean mIsIncoming;
@@ -82,8 +100,6 @@
      * service. */
     private final GatewayInfo mGatewayInfo;
 
-    private final Handler mHandler = new Handler();
-
     private long mConnectTimeMillis;
 
     /** The state of the call. */
@@ -226,6 +242,18 @@
         }
     }
 
+    String getName() {
+        return mCallerInfo == null ? null : mCallerInfo.name;
+    }
+
+    Bitmap getPhotoIcon() {
+        return mCallerInfo == null ? null : mCallerInfo.cachedPhotoIcon;
+    }
+
+    Drawable getPhoto() {
+        return mCallerInfo == null ? null : mCallerInfo.cachedPhoto;
+    }
+
     /**
      * @param disconnectCause The reason for the disconnection, any of
      *         {@link android.telephony.DisconnectCause}.
@@ -677,15 +705,43 @@
     }
 
     /**
-     * Saved the specified caller info if the specified token matches that of the last query
+     * Saves the specified caller info if the specified token matches that of the last query
      * that was made.
      *
      * @param callerInfo The new caller information to set.
      * @param token The token used with this query.
      */
     private void setCallerInfo(CallerInfo callerInfo, int token) {
+        Preconditions.checkNotNull(callerInfo);
+
         if (mQueryToken == token) {
             mCallerInfo = callerInfo;
+
+            if (mCallerInfo.person_id != 0) {
+                Uri personUri =
+                        ContentUris.withAppendedId(Contacts.CONTENT_URI, mCallerInfo.person_id);
+                Log.d(this, "Searching person uri %s for call %s", personUri, this);
+                ContactsAsyncHelper.startObtainPhotoAsync(
+                        token,
+                        TelecommApp.getInstance(),
+                        personUri,
+                        sPhotoLoadListener,
+                        this);
+            }
+        }
+    }
+
+    /**
+     * Saves the specified photo information if the specified token matches that of the last query.
+     *
+     * @param photo The photo as a drawable.
+     * @param photoIcon The photo as a small icon.
+     * @param token The token used with this query.
+     */
+    private void setPhoto(Drawable photo, Bitmap photoIcon, int token) {
+        if (mQueryToken == token) {
+            mCallerInfo.cachedPhoto = photo;
+            mCallerInfo.cachedPhotoIcon = photoIcon;
         }
     }
 }