use of com.android.dialer.phonelookup.PhoneLookupInfo in project android_packages_apps_Dialer by LineageOS.
the class CompositePhoneLookup method getMostRecentInfo.
/**
* Delegates to a set of dependent lookups and combines results.
*
* <p>Note: If any of the dependent lookups fails, the returned future will also fail. If any of
* the dependent lookups does not complete, the returned future will also not complete.
*/
@SuppressWarnings("unchecked")
public ListenableFuture<ImmutableMap<DialerPhoneNumber, PhoneLookupInfo>> getMostRecentInfo(ImmutableMap<DialerPhoneNumber, PhoneLookupInfo> existingInfoMap) {
return Futures.transformAsync(callLogState.isBuilt(), isBuilt -> {
Preconditions.checkNotNull(isBuilt);
List<ListenableFuture<ImmutableMap<DialerPhoneNumber, ?>>> futures = new ArrayList<>();
for (PhoneLookup phoneLookup : phoneLookups) {
futures.add(buildSubmapAndGetMostRecentInfo(existingInfoMap, phoneLookup, isBuilt));
}
ListenableFuture<ImmutableMap<DialerPhoneNumber, PhoneLookupInfo>> combinedFuture = Futures.transform(Futures.allAsList(futures), (allMaps) -> {
Preconditions.checkNotNull(allMaps);
ImmutableMap.Builder<DialerPhoneNumber, PhoneLookupInfo> combinedMap = ImmutableMap.builder();
for (DialerPhoneNumber dialerPhoneNumber : existingInfoMap.keySet()) {
PhoneLookupInfo.Builder combinedInfo = PhoneLookupInfo.newBuilder();
for (int i = 0; i < allMaps.size(); i++) {
ImmutableMap<DialerPhoneNumber, ?> map = allMaps.get(i);
Object subInfo = map.get(dialerPhoneNumber);
if (subInfo == null) {
throw new IllegalStateException("A sublookup didn't return an info for number: " + LogUtil.sanitizePhoneNumber(dialerPhoneNumber.getNormalizedNumber()));
}
phoneLookups.get(i).setSubMessage(combinedInfo, subInfo);
}
combinedMap.put(dialerPhoneNumber, combinedInfo.build());
}
return combinedMap.build();
}, lightweightExecutorService);
String eventName = getMostRecentInfoEventName(getLoggingName(), isBuilt);
futureTimer.applyTiming(combinedFuture, eventName);
return combinedFuture;
}, MoreExecutors.directExecutor());
}
use of com.android.dialer.phonelookup.PhoneLookupInfo in project android_packages_apps_Dialer by LineageOS.
the class Cp2DefaultDirectoryPhoneLookup method isDirty.
@Override
public ListenableFuture<Boolean> isDirty(ImmutableSet<DialerPhoneNumber> phoneNumbers) {
if (!PermissionsUtil.hasContactsReadPermissions(appContext)) {
LogUtil.w("Cp2DefaultDirectoryPhoneLookup.isDirty", "missing permissions");
Predicate<PhoneLookupInfo> phoneLookupInfoIsDirtyFn = phoneLookupInfo -> !phoneLookupInfo.getDefaultCp2Info().equals(Cp2Info.getDefaultInstance());
return missingPermissionsOperations.isDirtyForMissingPermissions(phoneNumbers, phoneLookupInfoIsDirtyFn);
}
PartitionedNumbers partitionedNumbers = new PartitionedNumbers(phoneNumbers);
if (partitionedNumbers.invalidNumbers().size() > getMaxSupportedInvalidNumbers()) {
// If there are N invalid numbers, we can't determine determine dirtiness without running N
// queries; since running this many queries is not feasible for the (lightweight) isDirty
// check, simply return true. The expectation is that this should rarely be the case as the
// vast majority of numbers in call logs should be valid.
LogUtil.v("Cp2DefaultDirectoryPhoneLookup.isDirty", "returning true because too many invalid numbers (%d)", partitionedNumbers.invalidNumbers().size());
return Futures.immediateFuture(true);
}
ListenableFuture<Long> lastModifiedFuture = backgroundExecutorService.submit(() -> sharedPreferences.getLong(PREF_LAST_TIMESTAMP_PROCESSED, 0L));
return Futures.transformAsync(lastModifiedFuture, lastModified -> {
// We are always going to need to do this check and it is pretty cheap so do it first.
ListenableFuture<Boolean> anyContactsDeletedFuture = anyContactsDeletedSince(lastModified);
return Futures.transformAsync(anyContactsDeletedFuture, anyContactsDeleted -> {
if (anyContactsDeleted) {
LogUtil.v("Cp2DefaultDirectoryPhoneLookup.isDirty", "returning true because contacts deleted");
return Futures.immediateFuture(true);
}
// Hopefully the most common case is there are no contacts updated; we can detect
// this cheaply.
ListenableFuture<Boolean> noContactsModifiedSinceFuture = noContactsModifiedSince(lastModified);
return Futures.transformAsync(noContactsModifiedSinceFuture, noContactsModifiedSince -> {
if (noContactsModifiedSince) {
LogUtil.v("Cp2DefaultDirectoryPhoneLookup.isDirty", "returning false because no contacts modified since last run");
return Futures.immediateFuture(false);
}
// This method is more expensive but is probably the most likely scenario; we
// are looking for changes to contacts which have been called.
ListenableFuture<Set<Long>> contactIdsFuture = queryPhoneTableForContactIds(phoneNumbers);
ListenableFuture<Boolean> contactsUpdatedFuture = Futures.transformAsync(contactIdsFuture, contactIds -> contactsUpdated(contactIds, lastModified), MoreExecutors.directExecutor());
return Futures.transformAsync(contactsUpdatedFuture, contactsUpdated -> {
if (contactsUpdated) {
LogUtil.v("Cp2DefaultDirectoryPhoneLookup.isDirty", "returning true because a previously called contact was updated");
return Futures.immediateFuture(true);
}
// This is the most expensive method so do it last; the scenario is that
// a contact which has been called got disassociated with a number and
// we need to clear their information.
ListenableFuture<Set<Long>> phoneLookupContactIdsFuture = queryPhoneLookupHistoryForContactIds();
return Futures.transformAsync(phoneLookupContactIdsFuture, phoneLookupContactIds -> contactsUpdated(phoneLookupContactIds, lastModified), MoreExecutors.directExecutor());
}, MoreExecutors.directExecutor());
}, MoreExecutors.directExecutor());
}, MoreExecutors.directExecutor());
}, MoreExecutors.directExecutor());
}
use of com.android.dialer.phonelookup.PhoneLookupInfo in project android_packages_apps_Dialer by LineageOS.
the class MissingPermissionsOperations method isDirtyForMissingPermissions.
/**
* Returns true if there is any CP2 data for the specified numbers in PhoneLookupHistory, because
* that data needs to be cleared.
*
* <p>Note: This might be a little slow for users without contacts permissions, but we don't
* expect this to often be the case. If necessary, a shared pref could be used to track the
* permission state as an optimization.
*/
ListenableFuture<Boolean> isDirtyForMissingPermissions(ImmutableSet<DialerPhoneNumber> phoneNumbers, Predicate<PhoneLookupInfo> phoneLookupInfoIsDirtyFn) {
return backgroundExecutor.submit(() -> {
// Note: This loses country info when number is not valid.
String[] normalizedNumbers = phoneNumbers.stream().map(DialerPhoneNumber::getNormalizedNumber).toArray(String[]::new);
Selection selection = Selection.builder().and(Selection.column(PhoneLookupHistory.NORMALIZED_NUMBER).in(normalizedNumbers)).build();
try (Cursor cursor = appContext.getContentResolver().query(PhoneLookupHistory.CONTENT_URI, new String[] { PhoneLookupHistory.PHONE_LOOKUP_INFO }, selection.getSelection(), selection.getSelectionArgs(), null)) {
if (cursor == null) {
LogUtil.w("MissingPermissionsOperations.isDirtyForMissingPermissions", "null cursor");
return false;
}
if (cursor.moveToFirst()) {
int phoneLookupInfoColumn = cursor.getColumnIndexOrThrow(PhoneLookupHistory.PHONE_LOOKUP_INFO);
do {
PhoneLookupInfo phoneLookupInfo;
try {
phoneLookupInfo = PhoneLookupInfo.parseFrom(cursor.getBlob(phoneLookupInfoColumn));
} catch (InvalidProtocolBufferException e) {
throw new IllegalStateException(e);
}
if (phoneLookupInfoIsDirtyFn.test(phoneLookupInfo)) {
return true;
}
} while (cursor.moveToNext());
}
}
return false;
});
}
use of com.android.dialer.phonelookup.PhoneLookupInfo in project android_packages_apps_Dialer by LineageOS.
the class BlockingCommand method run.
@Override
public ListenableFuture<String> run(Arguments args) throws IllegalCommandLineArgumentException {
if (args.getPositionals().isEmpty()) {
return Futures.immediateFuture(getUsage());
}
String command = args.getPositionals().get(0);
if ("block".equals(command)) {
String number = args.getPositionals().get(1);
return Futures.transform(Blocking.block(appContext, ImmutableList.of(number), null), (unused) -> "blocked " + number, MoreExecutors.directExecutor());
}
if ("unblock".equals(command)) {
String number = args.getPositionals().get(1);
return Futures.transform(Blocking.unblock(appContext, ImmutableList.of(number), null), (unused) -> "unblocked " + number, MoreExecutors.directExecutor());
}
if ("isblocked".equals(command)) {
String number = args.getPositionals().get(1);
ListenableFuture<DialerPhoneNumber> dialerPhoneNumberFuture = executorService.submit(() -> new DialerPhoneNumberUtil().parse(number, null));
ListenableFuture<PhoneLookupInfo> lookupFuture = Futures.transformAsync(dialerPhoneNumberFuture, (dialerPhoneNumber) -> PhoneLookupComponent.get(appContext).compositePhoneLookup().lookup(dialerPhoneNumber), executorService);
return Futures.transform(lookupFuture, (info) -> new PhoneLookupInfoConsolidator(info).isBlocked() ? "true" : "false", MoreExecutors.directExecutor());
}
return Futures.immediateFuture(getUsage());
}
use of com.android.dialer.phonelookup.PhoneLookupInfo in project android_packages_apps_Dialer by LineageOS.
the class RealtimeRowProcessor method applyRealtimeProcessing.
/**
* Converts a {@link CoalescedRow} to a future which is the result of performing additional work
* on the row. May simply return the original row if no modifications were necessary.
*/
@MainThread
ListenableFuture<CoalescedRow> applyRealtimeProcessing(final CoalescedRow row) {
// Cp2DefaultDirectoryPhoneLookup can not always efficiently process all rows.
if (!row.getNumberAttributes().getIsCp2InfoIncomplete()) {
return Futures.immediateFuture(row);
}
PhoneLookupInfo cachedPhoneLookupInfo = cache.get(row.getNumber());
if (cachedPhoneLookupInfo != null) {
return Futures.immediateFuture(applyPhoneLookupInfoToRow(cachedPhoneLookupInfo, row));
}
ListenableFuture<PhoneLookupInfo> phoneLookupInfoFuture = compositePhoneLookup.lookup(row.getNumber());
return Futures.transform(phoneLookupInfoFuture, phoneLookupInfo -> {
queuePhoneLookupHistoryWrite(row.getNumber(), phoneLookupInfo);
cache.put(row.getNumber(), phoneLookupInfo);
return applyPhoneLookupInfoToRow(phoneLookupInfo, row);
}, uiExecutor);
}
Aggregations