Add caller information lookup to Call.java

Bug: 15313021

Change-Id: I159a095965a158f59d01ce925fe08f4442a9e14b
diff --git a/src/com/android/telecomm/Call.java b/src/com/android/telecomm/Call.java
index 7488ffd..5eb2f97 100644
--- a/src/com/android/telecomm/Call.java
+++ b/src/com/android/telecomm/Call.java
@@ -18,6 +18,7 @@
 
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
 import android.telecomm.CallInfo;
 import android.telecomm.CallServiceDescriptor;
 import android.telecomm.CallState;
@@ -25,7 +26,11 @@
 import android.telecomm.TelecommConstants;
 import android.telephony.DisconnectCause;
 import android.telephony.PhoneNumberUtils;
+import android.text.TextUtils;
 
+import com.android.internal.telephony.CallerInfo;
+import com.android.internal.telephony.CallerInfoAsyncQuery;
+import com.android.internal.telephony.CallerInfoAsyncQuery.OnQueryCompleteListener;
 import com.google.android.collect.Sets;
 import com.google.common.base.Preconditions;
 
@@ -49,8 +54,16 @@
         void onFailedIncomingCall(Call call);
     }
 
-    /** Additional contact information beyond handle above, optional. */
-    private final ContactInfo mContactInfo;
+    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);
+                }
+            }
+        };
 
     /** True if this is an incoming call. */
     private final boolean mIsIncoming;
@@ -63,6 +76,14 @@
      */
     private final long mCreationTimeMillis = System.currentTimeMillis();
 
+    /** The gateway information associated with this call. This stores the original call handle
+     * that the user is attempting to connect to via the gateway, the actual handle to dial in
+     * order to connect the call via the gateway, as well as the package name of the gateway
+     * service. */
+    private final GatewayInfo mGatewayInfo;
+
+    private final Handler mHandler = new Handler();
+
     private long mConnectTimeMillis;
 
     /** The state of the call. */
@@ -71,12 +92,6 @@
     /** The handle with which to establish this call. */
     private Uri mHandle;
 
-    /** The gateway information associated with this call. This stores the original call handle
-     * that the user is attempting to connect to via the gateway, the actual handle to dial in
-     * order to connect the call via the gateway, as well as the package name of the gateway
-     * service. */
-    private final GatewayInfo mGatewayInfo;
-
     /**
      * The call service which is attempted or already connecting this call.
      */
@@ -133,27 +148,31 @@
     private CallServiceRepository mCallServiceRepository;
     private CallServiceSelectorRepository mSelectorRepository;
 
+    /** Caller information retrieved from the latest contact query. */
+    private CallerInfo mCallerInfo;
+
+    /** The latest token used with a contact info query. */
+    private int mQueryToken = 0;
+
     /**
      * Creates an empty call object.
      *
      * @param isIncoming True if this is an incoming call.
      */
     Call(boolean isIncoming) {
-        this(null, null, null, isIncoming);
+        this(null, null, isIncoming);
     }
 
     /**
      * Persists the specified parameters and initializes the new instance.
      *
      * @param handle The handle to dial.
-     * @param contactInfo Information about the entity being called.
      * @param gatewayInfo Gateway information to use for the call.
      * @param isIncoming True if this is an incoming call.
      */
-    Call(Uri handle, ContactInfo contactInfo, GatewayInfo gatewayInfo, boolean isIncoming) {
+    Call(Uri handle, GatewayInfo gatewayInfo, boolean isIncoming) {
         mState = CallState.NEW;
         setHandle(handle);
-        mContactInfo = contactInfo;
         mGatewayInfo = gatewayInfo;
         mIsIncoming = isIncoming;
     }
@@ -199,9 +218,12 @@
     }
 
     void setHandle(Uri handle) {
-        mHandle = handle;
-        mIsEmergencyCall = mHandle != null && PhoneNumberUtils.isLocalEmergencyNumber(
-                mHandle.getSchemeSpecificPart(), TelecommApp.getInstance());
+        if ((mHandle == null && handle != null) || (mHandle != null && !mHandle.equals(handle))) {
+            mHandle = handle;
+            mIsEmergencyCall = mHandle != null && PhoneNumberUtils.isLocalEmergencyNumber(
+                    mHandle.getSchemeSpecificPart(), TelecommApp.getInstance());
+            startCallerInfoLookup();
+        }
     }
 
     /**
@@ -243,10 +265,6 @@
         return mGatewayInfo;
     }
 
-    ContactInfo getContactInfo() {
-        return mContactInfo;
-    }
-
     boolean isIncoming() {
         return mIsIncoming;
     }
@@ -639,4 +657,35 @@
             binder.decrementAssociatedCallCount();
         }
     }
+
+    /**
+     * Looks up contact information based on the current handle.
+     */
+    private void startCallerInfoLookup() {
+        String number = mHandle == null ? null : mHandle.getSchemeSpecificPart();
+
+        mQueryToken++;  // Updated so that previous queries can no longer set the information.
+        mCallerInfo = null;
+        if (!TextUtils.isEmpty(number)) {
+            CallerInfoAsyncQuery.startQuery(
+                    mQueryToken,
+                    TelecommApp.getInstance(),
+                    number,
+                    sCallerInfoQueryListener,
+                    this);
+        }
+    }
+
+    /**
+     * Saved 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) {
+        if (mQueryToken == token) {
+            mCallerInfo = callerInfo;
+        }
+    }
 }
diff --git a/src/com/android/telecomm/CallLogManager.java b/src/com/android/telecomm/CallLogManager.java
index fcaf5f2..e7cdab4 100644
--- a/src/com/android/telecomm/CallLogManager.java
+++ b/src/com/android/telecomm/CallLogManager.java
@@ -104,7 +104,8 @@
         final long creationTime = call.getCreationTimeMillis();
         final long age = call.getAgeMillis();
 
-        final ContactInfo contactInfo = call.getContactInfo();  // May be null.
+        // TODO(santoscordon): Replace with use of call.getCallerInfo() or similar.
+        final ContactInfo contactInfo = null;
         final String logNumber = getLogNumber(call);
 
         Log.d(TAG, "logNumber set to: %s", Log.pii(logNumber));
diff --git a/src/com/android/telecomm/CallsManager.java b/src/com/android/telecomm/CallsManager.java
index 5ddba36..d41f483 100644
--- a/src/com/android/telecomm/CallsManager.java
+++ b/src/com/android/telecomm/CallsManager.java
@@ -221,7 +221,7 @@
                     Log.pii(uriHandle), Log.pii(handle));
         }
 
-        Call call = new Call(uriHandle, contactInfo, gatewayInfo, false /* isIncoming */);
+        Call call = new Call(uriHandle, gatewayInfo, false /* isIncoming */);
 
         // TODO(santoscordon): Move this to be a part of addCall()
         call.addListener(this);
@@ -390,8 +390,8 @@
         // original call will live on but its state will be updated to the new call's state. In
         // particular the original call's call service will be updated to the new call's call
         // service.
-        Call tempCall = new Call(originalCall.getHandoffHandle(), originalCall.getContactInfo(),
-                originalCall.getGatewayInfo(), false);
+        Call tempCall =
+                new Call(originalCall.getHandoffHandle(), originalCall.getGatewayInfo(), false);
         tempCall.setOriginalCall(originalCall);
         tempCall.setExtras(originalCall.getExtras());
         tempCall.setCallServiceSelector(originalCall.getCallServiceSelector());