Search in sources :

Example 1 with Cp2Info

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;
}
Also used : Cp2Info(com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info) ArraySet(android.support.v4.util.ArraySet) DialerPhoneNumber(com.android.dialer.DialerPhoneNumber) Cp2ContactInfo(com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info.Cp2ContactInfo)

Example 2 with Cp2Info

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);
}
Also used : Assert(com.android.dialer.common.Assert) Context(android.content.Context) LogUtil(com.android.dialer.common.LogUtil) Iterables(com.google.common.collect.Iterables) MoreExecutors(com.google.common.util.concurrent.MoreExecutors) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) Uri(android.net.Uri) DeletedContacts(android.provider.ContactsContract.DeletedContacts) Callable(java.util.concurrent.Callable) ConfigProvider(com.android.dialer.configprovider.ConfigProvider) Cp2Info(com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info) ArrayList(java.util.ArrayList) Inject(javax.inject.Inject) BackgroundExecutor(com.android.dialer.common.concurrent.Annotations.BackgroundExecutor) ContactsContract(android.provider.ContactsContract) PhoneLookup(com.android.dialer.phonelookup.PhoneLookup) ArrayMap(android.support.v4.util.ArrayMap) PartitionedNumbers(com.android.dialer.phonenumberproto.PartitionedNumbers) Unencrypted(com.android.dialer.storage.Unencrypted) Map(java.util.Map) PermissionsUtil(com.android.dialer.util.PermissionsUtil) Logger(com.android.dialer.logging.Logger) PhoneLookupHistory(com.android.dialer.phonelookup.database.contract.PhoneLookupHistoryContract.PhoneLookupHistory) ApplicationContext(com.android.dialer.inject.ApplicationContext) Cursor(android.database.Cursor) Contacts(android.provider.ContactsContract.Contacts) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) LightweightExecutor(com.android.dialer.common.concurrent.Annotations.LightweightExecutor) ImmutableSet(com.google.common.collect.ImmutableSet) PhoneLookupInfo(com.android.dialer.phonelookup.PhoneLookupInfo) ImmutableMap(com.google.common.collect.ImmutableMap) Predicate(java.util.function.Predicate) Set(java.util.Set) TextUtils(android.text.TextUtils) ArraySet(android.support.v4.util.ArraySet) Cp2ContactInfo(com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info.Cp2ContactInfo) Phone(android.provider.ContactsContract.CommonDataKinds.Phone) Maps(com.google.common.collect.Maps) DialerPhoneNumber(com.android.dialer.DialerPhoneNumber) Futures(com.google.common.util.concurrent.Futures) List(java.util.List) SharedPreferences(android.content.SharedPreferences) Entry(java.util.Map.Entry) Directory(android.provider.ContactsContract.Directory) Nullable(android.support.annotation.Nullable) ListeningExecutorService(com.google.common.util.concurrent.ListeningExecutorService) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) ArraySet(android.support.v4.util.ArraySet) Cp2ContactInfo(com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info.Cp2ContactInfo) ImmutableMap(com.google.common.collect.ImmutableMap) Cp2Info(com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info) DialerPhoneNumber(com.android.dialer.DialerPhoneNumber) ArrayMap(android.support.v4.util.ArrayMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap)

Example 3 with Cp2Info

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);
}
Also used : Cp2Info(com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info) ArrayList(java.util.ArrayList) ListenableFuture(com.google.common.util.concurrent.ListenableFuture)

Example 4 with Cp2Info

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;
    });
}
Also used : Cp2Info(com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info) ArraySet(android.support.v4.util.ArraySet) DialerPhoneNumber(com.android.dialer.DialerPhoneNumber) Cp2ContactInfo(com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info.Cp2ContactInfo) Cursor(android.database.Cursor)

Aggregations

Cp2Info (com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info)4 ArraySet (android.support.v4.util.ArraySet)3 DialerPhoneNumber (com.android.dialer.DialerPhoneNumber)3 Cp2ContactInfo (com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info.Cp2ContactInfo)3 Cursor (android.database.Cursor)2 ListenableFuture (com.google.common.util.concurrent.ListenableFuture)2 ArrayList (java.util.ArrayList)2 Context (android.content.Context)1 SharedPreferences (android.content.SharedPreferences)1 Uri (android.net.Uri)1 ContactsContract (android.provider.ContactsContract)1 Phone (android.provider.ContactsContract.CommonDataKinds.Phone)1 Contacts (android.provider.ContactsContract.Contacts)1 DeletedContacts (android.provider.ContactsContract.DeletedContacts)1 Directory (android.provider.ContactsContract.Directory)1 Nullable (android.support.annotation.Nullable)1 ArrayMap (android.support.v4.util.ArrayMap)1 TextUtils (android.text.TextUtils)1 Assert (com.android.dialer.common.Assert)1 LogUtil (com.android.dialer.common.LogUtil)1