Use the call log to cache additional contact information.
The new version of the call log needs a bit more information about the
matching contact (if any) to render its entries.
This change both uses the newly added columns in the call log to lookup
this values and stores the updated values back into the call log.
These values are used for setting up the quick contact badge and
formatting the phone number.
This also fixes a few smaller issues:
- the phone number shown used to change format between the initially set
value to the one obtained from the contact: this value is now cached.
- we were using -1 as the id of a non-existing contact, but 0 is
actually the value used elsewhere for this, so stick to that.
- make sure we use the cached value from the call log for formatting.
- update the call log if there was no previous value.
- introduce a UriUtils with a couple of useful functions for handling
URIs.
Bug: 5101753
Change-Id: I22f2b03b234da91e02dbeebe11a94c2f56295a3d
diff --git a/src/com/android/contacts/calllog/CallLogAdapter.java b/src/com/android/contacts/calllog/CallLogAdapter.java
index 7cd73a5..94daf06 100644
--- a/src/com/android/contacts/calllog/CallLogAdapter.java
+++ b/src/com/android/contacts/calllog/CallLogAdapter.java
@@ -22,6 +22,7 @@
import com.android.contacts.PhoneCallDetailsHelper;
import com.android.contacts.R;
import com.android.contacts.util.ExpirableCache;
+import com.android.contacts.util.UriUtils;
import com.google.common.annotations.VisibleForTesting;
import android.content.ContentValues;
@@ -90,6 +91,7 @@
private ViewTreeObserver.OnPreDrawListener mPreDrawListener;
private static final int REDRAW = 1;
private static final int START_THREAD = 2;
+
private boolean mFirst;
private Thread mCallerIdThread;
@@ -317,7 +319,7 @@
dataTableCursor.getColumnIndex(Data.CONTACT_ID));
String lookupKey = dataTableCursor.getString(
dataTableCursor.getColumnIndex(Data.LOOKUP_KEY));
- info.contactUri = Contacts.getLookupUri(contactId, lookupKey);
+ info.lookupUri = Contacts.getLookupUri(contactId, lookupKey);
info.name = dataTableCursor.getString(
dataTableCursor.getColumnIndex(Data.DISPLAY_NAME));
// "type" and "label" are currently unused for SIP addresses
@@ -326,8 +328,7 @@
// And "number" is the SIP address.
// Note Data.DATA1 and SipAddress.SIP_ADDRESS are equivalent.
- info.number = dataTableCursor.getString(
- dataTableCursor.getColumnIndex(Data.DATA1));
+ info.number = dataTableCursor.getString(dataTableCursor.getColumnIndex(Data.DATA1));
info.normalizedNumber = null; // meaningless for SIP addresses
info.photoId = dataTableCursor.getLong(
dataTableCursor.getColumnIndex(Data.PHOTO_ID));
@@ -366,14 +367,12 @@
info = new ContactInfo();
long contactId = phonesCursor.getLong(PhoneQuery.PERSON_ID);
String lookupKey = phonesCursor.getString(PhoneQuery.LOOKUP_KEY);
- info.contactUri = Contacts.getLookupUri(contactId, lookupKey);
+ info.lookupUri = Contacts.getLookupUri(contactId, lookupKey);
info.name = phonesCursor.getString(PhoneQuery.NAME);
info.type = phonesCursor.getInt(PhoneQuery.PHONE_TYPE);
info.label = phonesCursor.getString(PhoneQuery.LABEL);
- info.number = phonesCursor
- .getString(PhoneQuery.MATCHED_NUMBER);
- info.normalizedNumber = phonesCursor
- .getString(PhoneQuery.NORMALIZED_NUMBER);
+ info.number = phonesCursor.getString(PhoneQuery.MATCHED_NUMBER);
+ info.normalizedNumber = phonesCursor.getString(PhoneQuery.NORMALIZED_NUMBER);
info.photoId = phonesCursor.getLong(PhoneQuery.PHOTO_ID);
} else {
info = ContactInfo.EMPTY;
@@ -586,14 +585,15 @@
mContactInfoCache.getCachedValue(number);
ContactInfo info = cachedInfo == null ? null : cachedInfo.getValue();
if (cachedInfo == null) {
- // Mark it as empty and queue up a request to find the name.
+ mContactInfoCache.put(number, ContactInfo.EMPTY);
+ // Use the cached contact info from the call log.
+ info = cachedContactInfo;
// The db request should happen on a non-UI thread.
- info = ContactInfo.EMPTY;
- mContactInfoCache.put(number, info);
// Request the contact details immediately since they are currently missing.
enqueueRequest(number, cachedContactInfo, true);
// Format the phone number in the call log as best as we can.
- formattedNumber = formatPhoneNumber(number, null, countryIso);
+ formattedNumber = formatPhoneNumber(info.number, info.normalizedNumber, countryIso);
+ info.formattedNumber = formattedNumber;
} else {
if (cachedInfo.isExpired()) {
// The contact info is no longer up to date, we should request it. However, we
@@ -615,16 +615,15 @@
}
formattedNumber = info.formattedNumber;
} else {
+ // Use the cached contact info from the call log.
+ info = cachedContactInfo;
// Format the phone number in the call log as best as we can.
- formattedNumber = formatPhoneNumber(number, null, countryIso);
+ formattedNumber = formatPhoneNumber(info.number, info.normalizedNumber, countryIso);
+ info.formattedNumber = formattedNumber;
}
}
- if (info == null || info == ContactInfo.EMPTY) {
- info = cachedContactInfo;
- }
-
- final Uri contactUri = info.contactUri;
+ final Uri lookupUri = info.lookupUri;
final String name = info.name;
final int ntype = info.type;
final String label = info.label;
@@ -638,14 +637,14 @@
} else {
// We do not pass a photo id since we do not need the high-res picture.
details = new PhoneCallDetails(number, formattedNumber, countryIso, geocode,
- callTypes, date, duration, name, ntype, label, contactUri, null);
+ callTypes, date, duration, name, ntype, label, lookupUri, null);
}
final boolean isNew = CallLogQuery.isNewSection(c);
// New items also use the highlighted version of the text.
final boolean isHighlighted = isNew;
mCallLogViewsHelper.setPhoneCallDetails(views, details, isHighlighted);
- setPhoto(views, photoId, contactUri);
+ setPhoto(views, photoId, lookupUri);
// Listen for the first draw
if (mPreDrawListener == null) {
@@ -685,7 +684,31 @@
values.put(Calls.CACHED_NUMBER_LABEL, updatedInfo.label);
needsUpdate = true;
}
+ if (!UriUtils.areEqual(updatedInfo.lookupUri, callLogInfo.lookupUri)) {
+ values.put(Calls.CACHED_LOOKUP_URI, UriUtils.uriToString(updatedInfo.lookupUri));
+ needsUpdate = true;
+ }
+ if (!TextUtils.equals(updatedInfo.normalizedNumber, callLogInfo.normalizedNumber)) {
+ values.put(Calls.CACHED_NORMALIZED_NUMBER, updatedInfo.normalizedNumber);
+ needsUpdate = true;
+ }
+ if (!TextUtils.equals(updatedInfo.number, callLogInfo.number)) {
+ values.put(Calls.CACHED_MATCHED_NUMBER, updatedInfo.number);
+ needsUpdate = true;
+ }
+ if (updatedInfo.photoId != callLogInfo.photoId) {
+ values.put(Calls.CACHED_PHOTO_ID, updatedInfo.photoId);
+ needsUpdate = true;
+ }
} else {
+ // No previous values, store all of them.
+ values.put(Calls.CACHED_NAME, updatedInfo.name);
+ values.put(Calls.CACHED_NUMBER_TYPE, updatedInfo.type);
+ values.put(Calls.CACHED_NUMBER_LABEL, updatedInfo.label);
+ values.put(Calls.CACHED_LOOKUP_URI, UriUtils.uriToString(updatedInfo.lookupUri));
+ values.put(Calls.CACHED_MATCHED_NUMBER, updatedInfo.number);
+ values.put(Calls.CACHED_NORMALIZED_NUMBER, updatedInfo.normalizedNumber);
+ values.put(Calls.CACHED_PHOTO_ID, updatedInfo.photoId);
needsUpdate = true;
}
@@ -704,15 +727,16 @@
/** Returns the contact information as stored in the call log. */
private ContactInfo getContactInfoFromCallLog(Cursor c) {
ContactInfo info = new ContactInfo();
- info.contactUri = null;
+ info.lookupUri = UriUtils.parseUriOrNull(c.getString(CallLogQuery.CACHED_LOOKUP_URI));
info.name = c.getString(CallLogQuery.CACHED_NAME);
info.type = c.getInt(CallLogQuery.CACHED_NUMBER_TYPE);
info.label = c.getString(CallLogQuery.CACHED_NUMBER_LABEL);
- // TODO: This should be added to the call log cached values.
- info.number = c.getString(CallLogQuery.NUMBER);
- info.formattedNumber = info.number;
- info.normalizedNumber = info.number;
- info.photoId = 0;
+ String matchedNumber = c.getString(CallLogQuery.CACHED_MATCHED_NUMBER);
+ info.number = matchedNumber == null ? c.getString(CallLogQuery.NUMBER) : matchedNumber;
+ info.normalizedNumber = c.getString(CallLogQuery.CACHED_NORMALIZED_NUMBER);
+ info.photoId = c.getLong(CallLogQuery.CACHED_PHOTO_ID);
+ // TODO: This could be added to the call log cached values as well.
+ info.formattedNumber = null; // Computed on demand.
return info;
}
diff --git a/src/com/android/contacts/calllog/CallLogQuery.java b/src/com/android/contacts/calllog/CallLogQuery.java
index f596032..960097d 100644
--- a/src/com/android/contacts/calllog/CallLogQuery.java
+++ b/src/com/android/contacts/calllog/CallLogQuery.java
@@ -26,17 +26,21 @@
// If you alter this, you must also alter the method that inserts a fake row to the headers
// in the CallLogQueryHandler class called createHeaderCursorFor().
public static final String[] _PROJECTION = new String[] {
- Calls._ID,
- Calls.NUMBER,
- Calls.DATE,
- Calls.DURATION,
- Calls.TYPE,
- Calls.COUNTRY_ISO,
- Calls.VOICEMAIL_URI,
- Calls.GEOCODED_LOCATION,
- Calls.CACHED_NAME,
- Calls.CACHED_NUMBER_TYPE,
- Calls.CACHED_NUMBER_LABEL,
+ Calls._ID, // 0
+ Calls.NUMBER, // 1
+ Calls.DATE, // 2
+ Calls.DURATION, // 3
+ Calls.TYPE, // 4
+ Calls.COUNTRY_ISO, // 5
+ Calls.VOICEMAIL_URI, // 6
+ Calls.GEOCODED_LOCATION, // 7
+ Calls.CACHED_NAME, // 8
+ Calls.CACHED_NUMBER_TYPE, // 9
+ Calls.CACHED_NUMBER_LABEL, // 10
+ Calls.CACHED_LOOKUP_URI, // 11
+ Calls.CACHED_MATCHED_NUMBER, // 12
+ Calls.CACHED_NORMALIZED_NUMBER, // 13
+ Calls.CACHED_PHOTO_ID, // 14
};
public static final int ID = 0;
@@ -50,6 +54,12 @@
public static final int CACHED_NAME = 8;
public static final int CACHED_NUMBER_TYPE = 9;
public static final int CACHED_NUMBER_LABEL = 10;
+ public static final int CACHED_LOOKUP_URI = 11;
+ public static final int CACHED_MATCHED_NUMBER = 12;
+ public static final int CACHED_NORMALIZED_NUMBER = 13;
+ public static final int CACHED_PHOTO_ID = 14;
+ /** The index of the synthetic "section" column in the extended projection. */
+ public static final int SECTION = 15;
/**
* The name of the synthetic "section" column.
@@ -58,8 +68,6 @@
* part of the new or old calls.
*/
public static final String SECTION_NAME = "section";
- /** The index of the "section" column in the projection. */
- public static final int SECTION = 11;
/** The value of the "section" column for the header of the new section. */
public static final int SECTION_NEW_HEADER = 0;
/** The value of the "section" column for the items of the new section. */
diff --git a/src/com/android/contacts/calllog/CallLogQueryHandler.java b/src/com/android/contacts/calllog/CallLogQueryHandler.java
index 25beba5..f12f37e 100644
--- a/src/com/android/contacts/calllog/CallLogQueryHandler.java
+++ b/src/com/android/contacts/calllog/CallLogQueryHandler.java
@@ -106,7 +106,9 @@
new MatrixCursor(CallLogQuery.EXTENDED_PROJECTION);
// The values in this row correspond to default values for _PROJECTION from CallLogQuery
// plus the section value.
- matrixCursor.addRow(new Object[]{ -1L, "", 0L, 0L, 0, "", "", "", null, 0, null, section });
+ matrixCursor.addRow(new Object[]{
+ 0L, "", 0L, 0L, 0, "", "", "", null, 0, null, null, null, null, 0L, section
+ });
return matrixCursor;
}
diff --git a/src/com/android/contacts/calllog/ContactInfo.java b/src/com/android/contacts/calllog/ContactInfo.java
index c28018c..4dc5512 100644
--- a/src/com/android/contacts/calllog/ContactInfo.java
+++ b/src/com/android/contacts/calllog/ContactInfo.java
@@ -25,7 +25,7 @@
* Information for a contact as needed by the Call Log.
*/
public final class ContactInfo {
- public Uri contactUri;
+ public Uri lookupUri;
public String name;
public int type;
public String label;
@@ -41,10 +41,10 @@
public int hashCode() {
// Uses only name and contactUri to determine hashcode.
// This should be sufficient to have a reasonable distribution of hash codes.
- // Moreover, there should be no two people with the same contactUri.
+ // Moreover, there should be no two people with the same lookupUri.
final int prime = 31;
int result = 1;
- result = prime * result + ((contactUri == null) ? 0 : contactUri.hashCode());
+ result = prime * result + ((lookupUri == null) ? 0 : lookupUri.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@@ -55,7 +55,7 @@
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
ContactInfo other = (ContactInfo) obj;
- if (!UriUtils.areEqual(contactUri, other.contactUri)) return false;
+ if (!UriUtils.areEqual(lookupUri, other.lookupUri)) return false;
if (!TextUtils.equals(name, other.name)) return false;
if (type != other.type) return false;
if (!TextUtils.equals(label, other.label)) return false;
@@ -65,4 +65,4 @@
if (photoId != other.photoId) return false;
return true;
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/contacts/util/UriUtils.java b/src/com/android/contacts/util/UriUtils.java
index 7ef8786..c70d923 100644
--- a/src/com/android/contacts/util/UriUtils.java
+++ b/src/com/android/contacts/util/UriUtils.java
@@ -43,4 +43,9 @@
}
return Uri.parse(uriString);
}
+
+ /** Converts a URI into a string, returns null if the given URI is null. */
+ public static String uriToString(Uri uri) {
+ return uri == null ? null : uri.toString();
+ }
}
diff --git a/tests/src/com/android/contacts/activities/CallLogActivityTests.java b/tests/src/com/android/contacts/activities/CallLogActivityTests.java
index b148121..c1f31ae 100644
--- a/tests/src/com/android/contacts/activities/CallLogActivityTests.java
+++ b/tests/src/com/android/contacts/activities/CallLogActivityTests.java
@@ -67,7 +67,7 @@
private static final long NOW = -1L;
/** A test value for the URI of a contact. */
- private static final Uri TEST_CONTACT_URI = Uri.parse("content://contacts/2");
+ private static final Uri TEST_LOOKUP_URI = Uri.parse("content://contacts/2");
/** A test value for the country ISO of the phone number in the call log. */
private static final String TEST_COUNTRY_ISO = "US";
/** A phone number to be used in tests. */
@@ -450,7 +450,7 @@
String cachedName, int cachedNumberType, String cachedNumberLabel) {
insert(number, date, duration, type);
ContactInfo contactInfo = new ContactInfo();
- contactInfo.contactUri = TEST_CONTACT_URI;
+ contactInfo.lookupUri = TEST_LOOKUP_URI;
contactInfo.name = cachedName;
contactInfo.type = cachedNumberType;
contactInfo.label = cachedNumberLabel;
diff --git a/tests/src/com/android/contacts/calllog/CallLogQueryTestUtils.java b/tests/src/com/android/contacts/calllog/CallLogQueryTestUtils.java
index c273612..ff18477 100644
--- a/tests/src/com/android/contacts/calllog/CallLogQueryTestUtils.java
+++ b/tests/src/com/android/contacts/calllog/CallLogQueryTestUtils.java
@@ -28,7 +28,7 @@
public class CallLogQueryTestUtils {
public static Object[] createTestValues() {
Object[] values = new Object[]{
- -1L, "", 0L, 0L, Calls.INCOMING_TYPE, "", "", "", null, 0, null,
+ 0L, "", 0L, 0L, Calls.INCOMING_TYPE, "", "", "", null, 0, null, null, null, null, 0L
};
assertEquals(CallLogQuery._PROJECTION.length, values.length);
return values;
@@ -36,8 +36,8 @@
public static Object[] createTestExtendedValues() {
Object[] values = new Object[]{
- -1L, "", 0L, 0L, Calls.INCOMING_TYPE, "", "", "", null, 0, null,
- CallLogQuery.SECTION_OLD_ITEM
+ 0L, "", 0L, 0L, Calls.INCOMING_TYPE, "", "", "", null, 0, null, null, null, null,
+ 0L, CallLogQuery.SECTION_OLD_ITEM
};
Assert.assertEquals(CallLogQuery.EXTENDED_PROJECTION.length, values.length);
return values;