From 75812adca7fdebc90eb150035e399625f5c36a8b Mon Sep 17 00:00:00 2001 From: zachh Date: Tue, 12 Dec 2017 11:22:57 -0800 Subject: Updated writing of PhoneLookup columns in annotated call log. We're not going to use the "cached" columns from the system call log any longer, and instead will write them using PhoneLookup. Bug: 34672501 Test: unit PiperOrigin-RevId: 178788155 Change-Id: I9255dd3cb727eef3b45bc05aeb3c6fd6fd513d63 --- .../contract/AnnotatedCallLogContract.java | 16 ++--- .../phonelookup/PhoneLookupDataSource.java | 31 ++++++--- .../systemcalllog/SystemCallLogDataSource.java | 57 +++------------- .../dialer/phonelookup/PhoneLookupSelector.java | 79 ++++++++++++++++++++-- .../dialer/phonelookup/cp2/Cp2PhoneLookup.java | 77 ++++++++++++++------- .../dialer/phonelookup/phone_lookup_info.proto | 6 +- 6 files changed, 172 insertions(+), 94 deletions(-) (limited to 'java') diff --git a/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java b/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java index c9c053cea..7071ab5c1 100644 --- a/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java +++ b/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java @@ -42,10 +42,9 @@ public class AnnotatedCallLogContract { String TIMESTAMP = "timestamp"; /** - * Copied from {@link android.provider.CallLog.Calls#CACHED_NAME}. - * - *

This is exactly how it should appear to the user. If the user's locale or name display - * preferences change, this column should be rewritten. + * The name (which may be a person's name or business name, but not a number) formatted exactly + * as it should appear to the user. If the user's locale or name display preferences change, + * this column should be rewritten. * *

Type: TEXT */ @@ -61,28 +60,29 @@ public class AnnotatedCallLogContract { String NUMBER = "number"; /** - * Copied from {@link android.provider.CallLog.Calls#CACHED_FORMATTED_NUMBER}. + * The number formatted as it should be displayed to the user. Note that it may not always be + * displayed, for example if the number has a corresponding person or business name. * *

Type: TEXT */ String FORMATTED_NUMBER = "formatted_number"; /** - * Copied from {@link android.provider.CallLog.Calls#CACHED_PHOTO_URI}. + * A photo URI for the contact to display in the call log list view. * *

TYPE: TEXT */ String PHOTO_URI = "photo_uri"; /** - * Copied from {@link android.provider.CallLog.Calls#CACHED_PHOTO_ID}. + * A photo ID (from the contacts provider) for the contact to display in the call log list view. * *

Type: INTEGER (long) */ String PHOTO_ID = "photo_id"; /** - * Copied from {@link android.provider.CallLog.Calls#CACHED_LOOKUP_URI}. + * The contacts provider lookup URI for the contact associated with the call. * *

TYPE: TEXT */ diff --git a/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java b/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java index fa7d3be16..93e841409 100644 --- a/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java +++ b/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java @@ -32,6 +32,7 @@ import com.android.dialer.DialerPhoneNumber; import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog; import com.android.dialer.calllog.datasources.CallLogDataSource; import com.android.dialer.calllog.datasources.CallLogMutations; +import com.android.dialer.calllog.datasources.util.RowCombiner; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor; import com.android.dialer.common.concurrent.Annotations.LightweightExecutor; @@ -260,8 +261,13 @@ public final class PhoneLookupDataSource implements CallLogDataSource { @WorkerThread @Override public ContentValues coalesce(List individualRowsSortedByTimestampDesc) { - // TODO(zachh): Implementation. - return new ContentValues(); + return new RowCombiner(individualRowsSortedByTimestampDesc) + .useMostRecentString(AnnotatedCallLog.NAME) + .useMostRecentString(AnnotatedCallLog.NUMBER_TYPE_LABEL) + .useMostRecentString(AnnotatedCallLog.PHOTO_URI) + .useMostRecentLong(AnnotatedCallLog.PHOTO_ID) + .useMostRecentString(AnnotatedCallLog.LOOKUP_URI) + .combine(); } @MainThread @@ -434,7 +440,7 @@ public final class PhoneLookupDataSource implements CallLogDataSource { PhoneLookupInfo phoneLookupInfo = existingInfo.get(id); // Existing info might be missing if data was cleared or for other reasons. if (phoneLookupInfo != null) { - contentValues.put(AnnotatedCallLog.NAME, selectName(phoneLookupInfo)); + updateContentValues(contentValues, phoneLookupInfo); } } } @@ -474,17 +480,17 @@ public final class PhoneLookupDataSource implements CallLogDataSource { * mutations from PhoneLookupHistory; in this case "John" would be copied during * populateInserts() and there wouldn't be further updates needed here. */ - contentValuesToInsert.put(AnnotatedCallLog.NAME, selectName(phoneLookupInfo)); + updateContentValues(contentValuesToInsert, phoneLookupInfo); continue; } ContentValues contentValuesToUpdate = mutations.getUpdates().get(id); if (contentValuesToUpdate != null) { - contentValuesToUpdate.put(AnnotatedCallLog.NAME, selectName(phoneLookupInfo)); + updateContentValues(contentValuesToUpdate, phoneLookupInfo); continue; } // Else this row is not already scheduled for insert or update and we need to schedule it. ContentValues contentValues = new ContentValues(); - contentValues.put(AnnotatedCallLog.NAME, selectName(phoneLookupInfo)); + updateContentValues(contentValues, phoneLookupInfo); mutations.getUpdates().put(id, contentValues); } } @@ -525,8 +531,17 @@ public final class PhoneLookupDataSource implements CallLogDataSource { return normalizedNumbersToDelete; } - private static String selectName(PhoneLookupInfo phoneLookupInfo) { - return PhoneLookupSelector.selectName(phoneLookupInfo); + private static void updateContentValues( + ContentValues contentValues, PhoneLookupInfo phoneLookupInfo) { + contentValues.put(AnnotatedCallLog.NAME, PhoneLookupSelector.selectName(phoneLookupInfo)); + contentValues.put( + AnnotatedCallLog.PHOTO_URI, PhoneLookupSelector.selectPhotoUri(phoneLookupInfo)); + contentValues.put( + AnnotatedCallLog.PHOTO_ID, PhoneLookupSelector.selectPhotoId(phoneLookupInfo)); + contentValues.put( + AnnotatedCallLog.LOOKUP_URI, PhoneLookupSelector.selectLookupUri(phoneLookupInfo)); + contentValues.put( + AnnotatedCallLog.NUMBER_TYPE_LABEL, PhoneLookupSelector.selectNumberLabel(phoneLookupInfo)); } private static Uri numberUri(String number) { diff --git a/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java b/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java index 91db915ef..0ed185966 100644 --- a/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java +++ b/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java @@ -27,7 +27,6 @@ import android.os.Build; import android.os.Handler; import android.provider.CallLog; import android.provider.CallLog.Calls; -import android.provider.ContactsContract.CommonDataKinds.Phone; import android.support.annotation.ColorInt; import android.support.annotation.MainThread; import android.support.annotation.Nullable; @@ -35,6 +34,7 @@ import android.support.annotation.VisibleForTesting; import android.support.annotation.WorkerThread; import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; +import android.telephony.PhoneNumberUtils; import android.text.TextUtils; import android.util.ArraySet; import com.android.dialer.DialerPhoneNumber; @@ -174,23 +174,16 @@ public class SystemCallLogDataSource implements CallLogDataSource { @Override public ContentValues coalesce(List individualRowsSortedByTimestampDesc) { - // TODO(zachh): Complete implementation. - assertNoVoicemailsInRows(individualRowsSortedByTimestampDesc); return new RowCombiner(individualRowsSortedByTimestampDesc) .useMostRecentLong(AnnotatedCallLog.TIMESTAMP) .useMostRecentLong(AnnotatedCallLog.NEW) - .useMostRecentString(AnnotatedCallLog.NUMBER_TYPE_LABEL) - .useMostRecentString(AnnotatedCallLog.NAME) // Two different DialerPhoneNumbers could be combined if they are different but considered // to be an "exact match" by libphonenumber; in this case we arbitrarily select the most // recent one. .useMostRecentBlob(AnnotatedCallLog.NUMBER) .useMostRecentString(AnnotatedCallLog.FORMATTED_NUMBER) - .useMostRecentString(AnnotatedCallLog.PHOTO_URI) - .useMostRecentLong(AnnotatedCallLog.PHOTO_ID) - .useMostRecentString(AnnotatedCallLog.LOOKUP_URI) .useMostRecentString(AnnotatedCallLog.GEOCODED_LOCATION) .useSingleValueString(AnnotatedCallLog.PHONE_ACCOUNT_COMPONENT_NAME) .useSingleValueString(AnnotatedCallLog.PHONE_ACCOUNT_ID) @@ -233,13 +226,6 @@ public class SystemCallLogDataSource implements CallLogDataSource { Calls.NUMBER, Calls.TYPE, Calls.COUNTRY_ISO, - Calls.CACHED_NAME, - Calls.CACHED_FORMATTED_NUMBER, - Calls.CACHED_PHOTO_URI, - Calls.CACHED_PHOTO_ID, - Calls.CACHED_LOOKUP_URI, - Calls.CACHED_NUMBER_TYPE, - Calls.CACHED_NUMBER_LABEL, Calls.DURATION, Calls.DATA_USAGE, Calls.TRANSCRIPTION, @@ -272,14 +258,6 @@ public class SystemCallLogDataSource implements CallLogDataSource { int numberColumn = cursor.getColumnIndexOrThrow(Calls.NUMBER); int typeColumn = cursor.getColumnIndexOrThrow(Calls.TYPE); int countryIsoColumn = cursor.getColumnIndexOrThrow(Calls.COUNTRY_ISO); - int cachedNameColumn = cursor.getColumnIndexOrThrow(Calls.CACHED_NAME); - int cachedFormattedNumberColumn = - cursor.getColumnIndexOrThrow(Calls.CACHED_FORMATTED_NUMBER); - int cachedPhotoUriColumn = cursor.getColumnIndexOrThrow(Calls.CACHED_PHOTO_URI); - int cachedPhotoIdColumn = cursor.getColumnIndexOrThrow(Calls.CACHED_PHOTO_ID); - int cachedLookupUriColumn = cursor.getColumnIndexOrThrow(Calls.CACHED_LOOKUP_URI); - int cachedNumberTypeColumn = cursor.getColumnIndexOrThrow(Calls.CACHED_NUMBER_TYPE); - int cachedNumberLabelColumn = cursor.getColumnIndexOrThrow(Calls.CACHED_NUMBER_LABEL); int durationsColumn = cursor.getColumnIndexOrThrow(Calls.DURATION); int dataUsageColumn = cursor.getColumnIndexOrThrow(Calls.DATA_USAGE); int transcriptionColumn = cursor.getColumnIndexOrThrow(Calls.TRANSCRIPTION); @@ -301,13 +279,6 @@ public class SystemCallLogDataSource implements CallLogDataSource { String numberAsStr = cursor.getString(numberColumn); long type = cursor.getInt(typeColumn); String countryIso = cursor.getString(countryIsoColumn); - String cachedName = cursor.getString(cachedNameColumn); - String formattedNumber = cursor.getString(cachedFormattedNumberColumn); - String cachedPhotoUri = cursor.getString(cachedPhotoUriColumn); - long cachedPhotoId = cursor.getLong(cachedPhotoIdColumn); - String cachedLookupUri = cursor.getString(cachedLookupUriColumn); - int cachedNumberType = cursor.getInt(cachedNumberTypeColumn); - String cachedNumberLabel = cursor.getString(cachedNumberLabelColumn); int duration = cursor.getInt(durationsColumn); int dataUsage = cursor.getInt(dataUsageColumn); String transcription = cursor.getString(transcriptionColumn); @@ -323,31 +294,19 @@ public class SystemCallLogDataSource implements CallLogDataSource { contentValues.put(AnnotatedCallLog.TIMESTAMP, date); if (!TextUtils.isEmpty(numberAsStr)) { - byte[] numberAsProtoBytes = - dialerPhoneNumberUtil.parse(numberAsStr, countryIso).toByteArray(); + DialerPhoneNumber dialerPhoneNumber = + dialerPhoneNumberUtil.parse(numberAsStr, countryIso); + + contentValues.put(AnnotatedCallLog.NUMBER, dialerPhoneNumber.toByteArray()); + contentValues.put( + AnnotatedCallLog.FORMATTED_NUMBER, + PhoneNumberUtils.formatNumber(numberAsStr, countryIso)); // TODO(zachh): Need to handle post-dial digits; different on N and M. - contentValues.put(AnnotatedCallLog.NUMBER, numberAsProtoBytes); } else { contentValues.put( AnnotatedCallLog.NUMBER, DialerPhoneNumber.getDefaultInstance().toByteArray()); } - contentValues.put(AnnotatedCallLog.CALL_TYPE, type); - contentValues.put(AnnotatedCallLog.NAME, cachedName); - // TODO(zachh): Format the number using DialerPhoneNumberUtil here. - contentValues.put(AnnotatedCallLog.FORMATTED_NUMBER, formattedNumber); - contentValues.put(AnnotatedCallLog.PHOTO_URI, cachedPhotoUri); - contentValues.put(AnnotatedCallLog.PHOTO_ID, cachedPhotoId); - contentValues.put(AnnotatedCallLog.LOOKUP_URI, cachedLookupUri); - - // Phone.getTypeLabel returns "Custom" if given (0, null) which is not of any use. Just - // omit setting the label if there's no information for it. - if (cachedNumberType != 0 || cachedNumberLabel != null) { - contentValues.put( - AnnotatedCallLog.NUMBER_TYPE_LABEL, - Phone.getTypeLabel(appContext.getResources(), cachedNumberType, cachedNumberLabel) - .toString()); - } contentValues.put(AnnotatedCallLog.IS_READ, isRead); contentValues.put(AnnotatedCallLog.NEW, isNew); contentValues.put(AnnotatedCallLog.GEOCODED_LOCATION, geocodedLocation); diff --git a/java/com/android/dialer/phonelookup/PhoneLookupSelector.java b/java/com/android/dialer/phonelookup/PhoneLookupSelector.java index a746ea44f..af8b849e5 100644 --- a/java/com/android/dialer/phonelookup/PhoneLookupSelector.java +++ b/java/com/android/dialer/phonelookup/PhoneLookupSelector.java @@ -16,6 +16,8 @@ package com.android.dialer.phonelookup; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info.Cp2ContactInfo; /** * Prioritizes information from a {@link PhoneLookupInfo}. @@ -37,11 +39,80 @@ public final class PhoneLookupSelector { */ @NonNull public static String selectName(PhoneLookupInfo phoneLookupInfo) { - if (phoneLookupInfo.getCp2Info().getCp2ContactInfoCount() > 0) { - // Arbitrarily select the first contact's name. In the future, it may make sense to join the - // names such as "Mom, Dad" in the case that multiple contacts share the same number. - return phoneLookupInfo.getCp2Info().getCp2ContactInfo(0).getName(); + Cp2ContactInfo firstLocalContact = firstLocalContact(phoneLookupInfo); + if (firstLocalContact != null) { + String name = firstLocalContact.getName(); + if (!name.isEmpty()) { + return firstLocalContact.getName(); + } + } + return ""; + } + + /** Select the photo URI associated with this number. */ + @NonNull + public static String selectPhotoUri(PhoneLookupInfo phoneLookupInfo) { + Cp2ContactInfo firstLocalContact = firstLocalContact(phoneLookupInfo); + if (firstLocalContact != null) { + String photoUri = firstLocalContact.getPhotoUri(); + if (!photoUri.isEmpty()) { + return photoUri; + } + } + return ""; + } + + /** Select the photo ID associated with this number, or 0 if there is none. */ + public static long selectPhotoId(PhoneLookupInfo phoneLookupInfo) { + Cp2ContactInfo firstLocalContact = firstLocalContact(phoneLookupInfo); + if (firstLocalContact != null) { + long photoId = firstLocalContact.getPhotoId(); + if (photoId > 0) { + return photoId; + } + } + return 0; + } + + /** Select the lookup URI associated with this number. */ + @NonNull + public static String selectLookupUri(PhoneLookupInfo phoneLookupInfo) { + Cp2ContactInfo firstLocalContact = firstLocalContact(phoneLookupInfo); + if (firstLocalContact != null) { + String lookupUri = firstLocalContact.getLookupUri(); + if (!lookupUri.isEmpty()) { + return lookupUri; + } } return ""; } + + /** + * A localized string representing the number type such as "Home" or "Mobile", or a custom value + * set by the user. + */ + @NonNull + public static String selectNumberLabel(PhoneLookupInfo phoneLookupInfo) { + Cp2ContactInfo firstLocalContact = firstLocalContact(phoneLookupInfo); + if (firstLocalContact != null) { + String label = firstLocalContact.getLabel(); + if (!label.isEmpty()) { + return label; + } + } + return ""; + } + + /** + * Arbitrarily select the first contact. In the future, it may make sense to display contact + * information from all contacts with the same number (for example show the name as "Mom, Dad" or + * show a synthesized photo containing photos of both "Mom" and "Dad"). + */ + @Nullable + private static Cp2ContactInfo firstLocalContact(PhoneLookupInfo phoneLookupInfo) { + if (phoneLookupInfo.getCp2Info().getCp2ContactInfoCount() > 0) { + return phoneLookupInfo.getCp2Info().getCp2ContactInfo(0); + } + return null; + } } diff --git a/java/com/android/dialer/phonelookup/cp2/Cp2PhoneLookup.java b/java/com/android/dialer/phonelookup/cp2/Cp2PhoneLookup.java index 03e05b563..3829a8df1 100644 --- a/java/com/android/dialer/phonelookup/cp2/Cp2PhoneLookup.java +++ b/java/com/android/dialer/phonelookup/cp2/Cp2PhoneLookup.java @@ -58,17 +58,21 @@ public final class Cp2PhoneLookup implements PhoneLookup { Phone.DISPLAY_NAME_PRIMARY, // 0 Phone.PHOTO_THUMBNAIL_URI, // 1 Phone.PHOTO_ID, // 2 - Phone.LABEL, // 3 - Phone.NORMALIZED_NUMBER, // 4 - Phone.CONTACT_ID, // 5 + Phone.TYPE, // 3 + Phone.LABEL, // 4 + Phone.NORMALIZED_NUMBER, // 5 + Phone.CONTACT_ID, // 6 + Phone.LOOKUP_KEY // 7 }; private static final int CP2_INFO_NAME_INDEX = 0; private static final int CP2_INFO_PHOTO_URI_INDEX = 1; private static final int CP2_INFO_PHOTO_ID_INDEX = 2; - private static final int CP2_INFO_LABEL_INDEX = 3; - private static final int CP2_INFO_NUMBER_INDEX = 4; - private static final int CP2_INFO_CONTACT_ID_INDEX = 5; + private static final int CP2_INFO_TYPE_INDEX = 3; + private static final int CP2_INFO_LABEL_INDEX = 4; + private static final int CP2_INFO_NUMBER_INDEX = 5; + private static final int CP2_INFO_CONTACT_ID_INDEX = 6; + private static final int CP2_INFO_LOOKUP_KEY_INDEX = 7; private final Context appContext; private final SharedPreferences sharedPreferences; @@ -89,6 +93,7 @@ public final class Cp2PhoneLookup implements PhoneLookup { @Override public ListenableFuture lookup(@NonNull Call call) { // TODO(zachh): Implementation. + // TODO(zachh): Note: Should write empty Cp2Info even when no contact found. return backgroundExecutorService.submit(PhoneLookupInfo::getDefaultInstance); } @@ -207,7 +212,7 @@ public final class Cp2PhoneLookup implements PhoneLookup { // For each DialerPhoneNumber that was associated with a contact or added to a contact, // build a map of those DialerPhoneNumbers to a set Cp2ContactInfos, where each Cp2ContactInfo // represents a contact. - ImmutableMap> updatedContacts = + Map> updatedContacts = buildMapForUpdatedOrAddedContacts(existingInfoMap, lastModified, deletedPhoneNumbers); // Start build a new map of updated info. This will replace existing info. @@ -216,23 +221,26 @@ public final class Cp2PhoneLookup implements PhoneLookup { // For each DialerPhoneNumber in existing info... for (Entry entry : existingInfoMap.entrySet()) { + DialerPhoneNumber dialerPhoneNumber = entry.getKey(); + PhoneLookupInfo existingInfo = entry.getValue(); + // Build off the existing info - PhoneLookupInfo.Builder infoBuilder = PhoneLookupInfo.newBuilder(entry.getValue()); + PhoneLookupInfo.Builder infoBuilder = PhoneLookupInfo.newBuilder(existingInfo); // If the contact was updated, replace the Cp2ContactInfo list - if (updatedContacts.containsKey(entry.getKey())) { + if (updatedContacts.containsKey(dialerPhoneNumber)) { infoBuilder.setCp2Info( - Cp2Info.newBuilder().addAllCp2ContactInfo(updatedContacts.get(entry.getKey()))); + Cp2Info.newBuilder().addAllCp2ContactInfo(updatedContacts.get(dialerPhoneNumber))); // If it was deleted and not added to a new contact, replace the Cp2ContactInfo list with // the default instance of Cp2ContactInfo - } else if (deletedPhoneNumbers.contains(entry.getKey())) { + } else if (deletedPhoneNumbers.contains(dialerPhoneNumber)) { infoBuilder.setCp2Info( Cp2Info.newBuilder().addCp2ContactInfo(Cp2ContactInfo.getDefaultInstance())); } // If the DialerPhoneNumber didn't change, add the unchanged existing info. - newInfoMapBuilder.put(entry.getKey(), infoBuilder.build()); + newInfoMapBuilder.put(dialerPhoneNumber, infoBuilder.build()); } return newInfoMapBuilder.build(); } @@ -260,7 +268,7 @@ public final class Cp2PhoneLookup implements PhoneLookup { * @return Map of {@link DialerPhoneNumber} to {@link PhoneLookupInfo} with updated {@link * Cp2ContactInfo}. */ - private ImmutableMap> buildMapForUpdatedOrAddedContacts( + private Map> buildMapForUpdatedOrAddedContacts( ImmutableMap existingInfoMap, long lastModified, Set deletedPhoneNumbers) { @@ -270,16 +278,24 @@ public final class Cp2PhoneLookup implements PhoneLookup { Set contactIds = new ArraySet<>(); for (Entry entry : existingInfoMap.entrySet()) { + DialerPhoneNumber dialerPhoneNumber = entry.getKey(); + PhoneLookupInfo existingInfo = entry.getValue(); + // If the number was deleted, we need to check if it was added to a new contact. - if (deletedPhoneNumbers.contains(entry.getKey())) { - updatedNumbers.add(entry.getKey()); + if (deletedPhoneNumbers.contains(dialerPhoneNumber)) { + updatedNumbers.add(dialerPhoneNumber); continue; } + // Note: Methods in this class must always set at least one Cp2Info, setting it to + // getDefaultInstance() if there is no information for the contact. + Assert.checkState( + existingInfo.getCp2Info().getCp2ContactInfoCount() > 0, "existing info has no cp2 infos"); + // For each Cp2ContactInfo for each existing DialerPhoneNumber... // Store the contact id if it exist, else automatically add the DialerPhoneNumber to our // set of DialerPhoneNumbers we want to update. - for (Cp2ContactInfo cp2ContactInfo : entry.getValue().getCp2Info().getCp2ContactInfoList()) { + for (Cp2ContactInfo cp2ContactInfo : existingInfo.getCp2Info().getCp2ContactInfoList()) { if (Objects.equals(cp2ContactInfo, Cp2ContactInfo.getDefaultInstance())) { // If the number doesn't have any Cp2ContactInfo set to it, for various reasons, we need // to look up the number to check if any exists. @@ -287,7 +303,7 @@ public final class Cp2PhoneLookup implements PhoneLookup { // - An existing contact that wasn't in the call log is now in the call log. // - A number was in the call log before but has now been added to a contact. // - A number is in the call log, but isn't associated with any contact. - updatedNumbers.add(entry.getKey()); + updatedNumbers.add(dialerPhoneNumber); } else { contactIds.add(cp2ContactInfo.getContactId()); } @@ -322,7 +338,7 @@ public final class Cp2PhoneLookup implements PhoneLookup { // Map each dialer phone number to it's new cp2 info Set phoneNumbers = getDialerPhoneNumbers(updatedNumbers, cursor.getString(CP2_INFO_NUMBER_INDEX)); - Cp2ContactInfo info = buildCp2ContactInfoFromUpdatedContactsCursor(cursor); + Cp2ContactInfo info = buildCp2ContactInfoFromUpdatedContactsCursor(appContext, cursor); for (DialerPhoneNumber phoneNumber : phoneNumbers) { if (map.containsKey(phoneNumber)) { map.get(phoneNumber).add(info); @@ -334,7 +350,7 @@ public final class Cp2PhoneLookup implements PhoneLookup { } } } - return ImmutableMap.copyOf(map); + return map; } /** @@ -358,10 +374,15 @@ public final class Cp2PhoneLookup implements PhoneLookup { * @param cursor with projection {@link #CP2_INFO_PROJECTION}. * @return new {@link Cp2ContactInfo} based on current row of {@code cursor}. */ - private static Cp2ContactInfo buildCp2ContactInfoFromUpdatedContactsCursor(Cursor cursor) { + private static Cp2ContactInfo buildCp2ContactInfoFromUpdatedContactsCursor( + Context appContext, Cursor cursor) { String displayName = cursor.getString(CP2_INFO_NAME_INDEX); String photoUri = cursor.getString(CP2_INFO_PHOTO_URI_INDEX); + int photoId = cursor.getInt(CP2_INFO_PHOTO_ID_INDEX); + int type = cursor.getInt(CP2_INFO_TYPE_INDEX); String label = cursor.getString(CP2_INFO_LABEL_INDEX); + int contactId = cursor.getInt(CP2_INFO_CONTACT_ID_INDEX); + String lookupKey = cursor.getString(CP2_INFO_LOOKUP_KEY_INDEX); Cp2ContactInfo.Builder infoBuilder = Cp2ContactInfo.newBuilder(); if (!TextUtils.isEmpty(displayName)) { @@ -370,11 +391,19 @@ public final class Cp2PhoneLookup implements PhoneLookup { if (!TextUtils.isEmpty(photoUri)) { infoBuilder.setPhotoUri(photoUri); } - if (!TextUtils.isEmpty(label)) { - infoBuilder.setLabel(label); + if (photoId > 0) { + infoBuilder.setPhotoId(photoId); + } + + // Phone.getTypeLabel returns "Custom" if given (0, null) which is not of any use. Just + // omit setting the label if there's no information for it. + if (type != 0 || !TextUtils.isEmpty(label)) { + infoBuilder.setLabel(Phone.getTypeLabel(appContext.getResources(), type, label).toString()); + } + infoBuilder.setContactId(contactId); + if (!TextUtils.isEmpty(lookupKey)) { + infoBuilder.setLookupUri(Contacts.getLookupUri(contactId, lookupKey).toString()); } - infoBuilder.setPhotoId(cursor.getLong(CP2_INFO_PHOTO_ID_INDEX)); - infoBuilder.setContactId(cursor.getLong(CP2_INFO_CONTACT_ID_INDEX)); return infoBuilder.build(); } diff --git a/java/com/android/dialer/phonelookup/phone_lookup_info.proto b/java/com/android/dialer/phonelookup/phone_lookup_info.proto index 93dd01e86..36596c1a2 100644 --- a/java/com/android/dialer/phonelookup/phone_lookup_info.proto +++ b/java/com/android/dialer/phonelookup/phone_lookup_info.proto @@ -34,9 +34,13 @@ message PhoneLookupInfo { // android.provider.ContactsContract.CommonDataKinds.Phone.CONTACT_ID optional fixed64 contact_id = 5; + + // android.provider.ContactsContract.CONTENT_LOOKUP_URI + optional string lookup_uri = 6; } // Repeated because one phone number can be associated with multiple CP2 - // contacts. + // contacts. If no contact is found for a number, this will contain exactly + // one element which is the default Cp2ContactInfo instance. repeated Cp2ContactInfo cp2_contact_info = 1; } optional Cp2Info cp2_info = 1; -- cgit v1.2.3