use of com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info in project android_packages_apps_Dialer by LineageOS.
the class Cp2DefaultDirectoryPhoneLookup method findDialerPhoneNumbersContainingContactId.
private static Set<DialerPhoneNumber> findDialerPhoneNumbersContainingContactId(Map<DialerPhoneNumber, Cp2Info> existingInfoMap, long contactId) {
Set<DialerPhoneNumber> matches = new ArraySet<>();
for (Entry<DialerPhoneNumber, Cp2Info> entry : existingInfoMap.entrySet()) {
for (Cp2ContactInfo cp2ContactInfo : entry.getValue().getCp2ContactInfoList()) {
if (cp2ContactInfo.getContactId() == contactId) {
matches.add(entry.getKey());
}
}
}
Assert.checkArgument(matches.size() > 0, "Couldn't find DialerPhoneNumber for contact ID: " + contactId);
return matches;
}
use of com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info in project android_packages_apps_Dialer by LineageOS.
the class Cp2DefaultDirectoryPhoneLookup method getMostRecentInfo.
@Override
public ListenableFuture<ImmutableMap<DialerPhoneNumber, Cp2Info>> getMostRecentInfo(ImmutableMap<DialerPhoneNumber, Cp2Info> existingInfoMap) {
currentLastTimestampProcessed = null;
if (!PermissionsUtil.hasContactsReadPermissions(appContext)) {
LogUtil.w("Cp2DefaultDirectoryPhoneLookup.getMostRecentInfo", "missing permissions");
return missingPermissionsOperations.getMostRecentInfoForMissingPermissions(existingInfoMap);
}
ListenableFuture<Long> lastModifiedFuture = backgroundExecutorService.submit(() -> sharedPreferences.getLong(PREF_LAST_TIMESTAMP_PROCESSED, 0L));
return Futures.transformAsync(lastModifiedFuture, lastModified -> {
// Build a set of each DialerPhoneNumber that was associated with a contact, and is no
// longer associated with that same contact.
ListenableFuture<Set<DialerPhoneNumber>> deletedPhoneNumbersFuture = getDeletedPhoneNumbers(existingInfoMap, lastModified);
return Futures.transformAsync(deletedPhoneNumbersFuture, deletedPhoneNumbers -> {
// If there are too many invalid numbers, just defer the work to render time.
ArraySet<DialerPhoneNumber> unprocessableNumbers = findUnprocessableNumbers(existingInfoMap);
Map<DialerPhoneNumber, Cp2Info> existingInfoMapToProcess = existingInfoMap;
if (!unprocessableNumbers.isEmpty()) {
existingInfoMapToProcess = Maps.filterKeys(existingInfoMap, number -> !unprocessableNumbers.contains(number));
}
// 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.
ListenableFuture<Map<DialerPhoneNumber, Set<Cp2ContactInfo>>> updatedContactsFuture = buildMapForUpdatedOrAddedContacts(existingInfoMapToProcess, lastModified, deletedPhoneNumbers);
return Futures.transform(updatedContactsFuture, updatedContacts -> {
// Start build a new map of updated info. This will replace existing info.
ImmutableMap.Builder<DialerPhoneNumber, Cp2Info> newInfoMapBuilder = ImmutableMap.builder();
// For each DialerPhoneNumber in existing info...
for (Entry<DialerPhoneNumber, Cp2Info> entry : existingInfoMap.entrySet()) {
DialerPhoneNumber dialerPhoneNumber = entry.getKey();
Cp2Info existingInfo = entry.getValue();
// Build off the existing info
Cp2Info.Builder infoBuilder = Cp2Info.newBuilder(existingInfo);
// If the contact was updated, replace the Cp2ContactInfo list
if (updatedContacts.containsKey(dialerPhoneNumber)) {
infoBuilder.clear().addAllCp2ContactInfo(updatedContacts.get(dialerPhoneNumber));
// If it was deleted and not added to a new contact, clear all the CP2
// information.
} else if (deletedPhoneNumbers.contains(dialerPhoneNumber)) {
infoBuilder.clear();
} else if (unprocessableNumbers.contains(dialerPhoneNumber)) {
// does not have the ability to fetch information at render time).
if (!dialerPhoneNumber.getNormalizedNumber().isEmpty()) {
// Don't clear the existing info when the number is unprocessable. It's
// likely that the existing info is up-to-date so keep it in place so
// that the UI doesn't pop when the query is completed at display time.
infoBuilder.setIsIncomplete(true);
}
}
// If the DialerPhoneNumber didn't change, add the unchanged existing info.
newInfoMapBuilder.put(dialerPhoneNumber, infoBuilder.build());
}
return newInfoMapBuilder.build();
}, lightweightExecutorService);
}, lightweightExecutorService);
}, lightweightExecutorService);
}
use of com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info in project android_packages_apps_Dialer by LineageOS.
the class Cp2ExtendedDirectoryPhoneLookup method queryCp2ForDirectoryContact.
private ListenableFuture<Cp2Info> queryCp2ForDirectoryContact(DialerPhoneNumber dialerPhoneNumber, List<Long> directoryIds) {
if (directoryIds.isEmpty()) {
return Futures.immediateFuture(Cp2Info.getDefaultInstance());
}
// Note: This loses country info when number is not valid.
String number = dialerPhoneNumber.getNormalizedNumber();
List<ListenableFuture<Cp2Info>> cp2InfoFutures = new ArrayList<>();
for (long directoryId : directoryIds) {
cp2InfoFutures.add(queryCp2ForDirectoryContact(number, directoryId));
}
return Futures.transform(Futures.allAsList(cp2InfoFutures), cp2InfoList -> {
Cp2Info.Builder cp2InfoBuilder = Cp2Info.newBuilder();
for (Cp2Info cp2Info : cp2InfoList) {
cp2InfoBuilder.addAllCp2ContactInfo(cp2Info.getCp2ContactInfoList());
}
return cp2InfoBuilder.build();
}, lightweightExecutorService);
}
use of com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info in project android_packages_apps_Dialer by LineageOS.
the class Cp2DefaultDirectoryPhoneLookup method findNumbersToUpdate.
private ListenableFuture<Set<DialerPhoneNumber>> findNumbersToUpdate(Map<DialerPhoneNumber, Cp2Info> existingInfoMap, long lastModified, Set<DialerPhoneNumber> deletedPhoneNumbers) {
return backgroundExecutorService.submit(() -> {
Set<DialerPhoneNumber> updatedNumbers = new ArraySet<>();
Set<Long> contactIds = new ArraySet<>();
for (Entry<DialerPhoneNumber, Cp2Info> entry : existingInfoMap.entrySet()) {
DialerPhoneNumber dialerPhoneNumber = entry.getKey();
Cp2Info existingInfo = entry.getValue();
// If the number was deleted, we need to check if it was added to a new contact.
if (deletedPhoneNumbers.contains(dialerPhoneNumber)) {
updatedNumbers.add(dialerPhoneNumber);
continue;
}
// updated info.
if (existingInfo.getCp2ContactInfoCount() == 0) {
updatedNumbers.add(dialerPhoneNumber);
} else {
// our set of DialerPhoneNumbers we want to update.
for (Cp2ContactInfo cp2ContactInfo : existingInfo.getCp2ContactInfoList()) {
long existingContactId = cp2ContactInfo.getContactId();
if (existingContactId == 0) {
// If the number doesn't have a contact id, for various reasons, we need to look
// up the number to check if any exists. The various reasons this might happen
// are:
// - 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(dialerPhoneNumber);
} else {
contactIds.add(cp2ContactInfo.getContactId());
}
}
}
}
// is in our set of contact IDs we build above.
if (!contactIds.isEmpty()) {
try (Cursor cursor = queryContactsTableForContacts(contactIds, lastModified)) {
int contactIdIndex = cursor.getColumnIndex(Contacts._ID);
int lastUpdatedIndex = cursor.getColumnIndex(Contacts.CONTACT_LAST_UPDATED_TIMESTAMP);
cursor.moveToPosition(-1);
while (cursor.moveToNext()) {
// Find the DialerPhoneNumber for each contact id and add it to our updated numbers
// set. These, along with our number not associated with any Cp2ContactInfo need to
// be updated.
long contactId = cursor.getLong(contactIdIndex);
updatedNumbers.addAll(findDialerPhoneNumbersContainingContactId(existingInfoMap, contactId));
long lastUpdatedTimestamp = cursor.getLong(lastUpdatedIndex);
if (currentLastTimestampProcessed == null || currentLastTimestampProcessed < lastUpdatedTimestamp) {
currentLastTimestampProcessed = lastUpdatedTimestamp;
}
}
}
}
return updatedNumbers;
});
}
Aggregations