use of com.android.dialer.DialerPhoneNumber in project android_packages_apps_Dialer by LineageOS.
the class PhoneLookupDataSource method collectIdAndNumberFromAnnotatedCallLogAndPendingInserts.
private Map<DialerPhoneNumber, Set<Long>> collectIdAndNumberFromAnnotatedCallLogAndPendingInserts(Context appContext, CallLogMutations mutations) {
Map<DialerPhoneNumber, Set<Long>> idsByNumber = new ArrayMap<>();
// First add any pending inserts to the map.
for (Entry<Long, ContentValues> entry : mutations.getInserts().entrySet()) {
long id = entry.getKey();
ContentValues insertedContentValues = entry.getValue();
DialerPhoneNumber dialerPhoneNumber;
try {
dialerPhoneNumber = DialerPhoneNumber.parseFrom(insertedContentValues.getAsByteArray(AnnotatedCallLog.NUMBER));
} catch (InvalidProtocolBufferException e) {
throw new IllegalStateException(e);
}
Set<Long> ids = idsByNumber.get(dialerPhoneNumber);
if (ids == null) {
ids = new ArraySet<>();
idsByNumber.put(dialerPhoneNumber, ids);
}
ids.add(id);
}
try (Cursor cursor = appContext.getContentResolver().query(AnnotatedCallLog.CONTENT_URI, new String[] { AnnotatedCallLog._ID, AnnotatedCallLog.NUMBER }, null, null, null)) {
if (cursor == null) {
LogUtil.e("PhoneLookupDataSource.collectIdAndNumberFromAnnotatedCallLogAndPendingInserts", "null cursor");
return ImmutableMap.of();
}
if (cursor.moveToFirst()) {
int idColumn = cursor.getColumnIndexOrThrow(AnnotatedCallLog._ID);
int numberColumn = cursor.getColumnIndexOrThrow(AnnotatedCallLog.NUMBER);
do {
long id = cursor.getLong(idColumn);
byte[] blob = cursor.getBlob(numberColumn);
if (blob == null) {
// Not all [incoming] calls have associated phone numbers.
continue;
}
DialerPhoneNumber dialerPhoneNumber;
try {
dialerPhoneNumber = DialerPhoneNumber.parseFrom(blob);
} catch (InvalidProtocolBufferException e) {
throw new IllegalStateException(e);
}
Set<Long> ids = idsByNumber.get(dialerPhoneNumber);
if (ids == null) {
ids = new ArraySet<>();
idsByNumber.put(dialerPhoneNumber, ids);
}
ids.add(id);
} while (cursor.moveToNext());
}
}
return idsByNumber;
}
use of com.android.dialer.DialerPhoneNumber in project android_packages_apps_Dialer by LineageOS.
the class RealtimeRowProcessor method writePhoneLookupHistory.
@MainThread
private void writePhoneLookupHistory() {
Assert.isMainThread();
// Copy the batch to a new collection that be safely processed on a background thread.
ImmutableMap<DialerPhoneNumber, PhoneLookupInfo> currentBatch = ImmutableMap.copyOf(queuedPhoneLookupHistoryWrites);
// Clear the queue, handing responsibility for its items to the background task.
queuedPhoneLookupHistoryWrites.clear();
// Returns the number of rows updated.
ListenableFuture<Integer> applyBatchFuture = backgroundExecutor.submit(() -> {
ArrayList<ContentProviderOperation> operations = new ArrayList<>();
long currentTimestamp = System.currentTimeMillis();
for (Entry<DialerPhoneNumber, PhoneLookupInfo> entry : currentBatch.entrySet()) {
DialerPhoneNumber dialerPhoneNumber = entry.getKey();
PhoneLookupInfo phoneLookupInfo = entry.getValue();
// Note: Multiple DialerPhoneNumbers can map to the same normalized number but we
// just write them all and the value for the last one will arbitrarily win.
// Note: This loses country info when number is not valid.
String normalizedNumber = dialerPhoneNumber.getNormalizedNumber();
ContentValues contentValues = new ContentValues();
contentValues.put(PhoneLookupHistory.PHONE_LOOKUP_INFO, phoneLookupInfo.toByteArray());
contentValues.put(PhoneLookupHistory.LAST_MODIFIED, currentTimestamp);
operations.add(ContentProviderOperation.newUpdate(PhoneLookupHistory.contentUriForNumber(normalizedNumber)).withValues(contentValues).build());
}
return Assert.isNotNull(appContext.getContentResolver().applyBatch(PhoneLookupHistoryContract.AUTHORITY, operations)).length;
});
Futures.addCallback(applyBatchFuture, new FutureCallback<Integer>() {
@Override
public void onSuccess(Integer rowsAffected) {
LogUtil.i("RealtimeRowProcessor.onSuccess", "wrote %d rows to PhoneLookupHistory", rowsAffected);
}
@Override
public void onFailure(Throwable throwable) {
throw new RuntimeException(throwable);
}
}, uiExecutor);
}
use of com.android.dialer.DialerPhoneNumber in project android_packages_apps_Dialer by LineageOS.
the class CallLogCacheUpdater method updateCacheInternal.
private void updateCacheInternal(CallLogMutations mutations) {
ArrayList<ContentProviderOperation> operations = new ArrayList<>();
Stream.concat(mutations.getInserts().entrySet().stream(), mutations.getUpdates().entrySet().stream()).limit(CACHE_UPDATE_LIMIT).forEach(entry -> {
ContentValues values = entry.getValue();
if (!values.containsKey(AnnotatedCallLog.NUMBER_ATTRIBUTES) || !values.containsKey(AnnotatedCallLog.NUMBER)) {
return;
}
DialerPhoneNumber dialerPhoneNumber = ProtoParsers.getTrusted(values, AnnotatedCallLog.NUMBER, DialerPhoneNumber.getDefaultInstance());
NumberAttributes numberAttributes = ProtoParsers.getTrusted(values, AnnotatedCallLog.NUMBER_ATTRIBUTES, NumberAttributes.getDefaultInstance());
operations.add(ContentProviderOperation.newUpdate(ContentUris.withAppendedId(Calls.CONTENT_URI, entry.getKey())).withValue(Calls.CACHED_FORMATTED_NUMBER, values.getAsString(AnnotatedCallLog.FORMATTED_NUMBER)).withValue(Calls.CACHED_LOOKUP_URI, numberAttributes.getLookupUri()).withValue(Calls.CACHED_NAME, numberAttributes.getName()).withValue(Calls.CACHED_NORMALIZED_NUMBER, dialerPhoneNumber.getNormalizedNumber()).withValue(Calls.CACHED_NUMBER_LABEL, numberAttributes.getNumberTypeLabel()).withValue(Calls.CACHED_NUMBER_TYPE, Phone.TYPE_CUSTOM).withValue(Calls.CACHED_PHOTO_ID, numberAttributes.getPhotoId()).withValue(Calls.CACHED_PHOTO_URI, numberAttributes.getPhotoUri()).withSelection(Calls.CACHED_NAME + " IS NOT ?", new String[] { numberAttributes.getName() }).build());
});
try {
int count = Arrays.stream(appContext.getContentResolver().applyBatch(CallLog.AUTHORITY, operations)).mapToInt(result -> result.count).sum();
LogUtil.i("CallLogCacheUpdater.updateCache", "updated %d rows", count);
} catch (OperationApplicationException | RemoteException e) {
throw new IllegalStateException(e);
}
}
use of com.android.dialer.DialerPhoneNumber in project android_packages_apps_Dialer by LineageOS.
the class PhoneLookup method lookup.
/**
* Returns a future containing a new info for the number associated with the provided call.
*
* <p>The returned message should contain populated data for the sub-message corresponding to this
* {@link PhoneLookup}. For example, the CP2 implementation returns a {@link
* PhoneLookupInfo.Cp2Info} sub-message.
*
* <p>The default implementation is for all {@link PhoneLookup} implementations that don't need
* info in the given call, i.e., it simply extracts the phone number from the call and delegates
* to {@link #lookup(DialerPhoneNumber)}.
*
* <p>However, for {@link PhoneLookup} implementations that need info in the call (such as one for
* CNAP), they should override this method.
*/
default ListenableFuture<T> lookup(Context appContext, Call call) {
ListeningExecutorService backgroundExecutor = DialerExecutorComponent.get(appContext).backgroundExecutor();
ListenableFuture<DialerPhoneNumber> numberFuture = backgroundExecutor.submit(() -> {
DialerPhoneNumberUtil dialerPhoneNumberUtil = new DialerPhoneNumberUtil();
return dialerPhoneNumberUtil.parse(TelecomCallUtil.getNumber(call), GeoUtil.getCurrentCountryIso(appContext));
});
return Futures.transformAsync(numberFuture, this::lookup, MoreExecutors.directExecutor());
}
use of com.android.dialer.DialerPhoneNumber 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());
}
Aggregations