Search in sources :

Example 6 with DialerPhoneNumber

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;
}
Also used : ContentValues(android.content.ContentValues) ArraySet(android.util.ArraySet) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) ArrayMap(android.util.ArrayMap) Cursor(android.database.Cursor) DialerPhoneNumber(com.android.dialer.DialerPhoneNumber)

Example 7 with DialerPhoneNumber

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);
}
Also used : ContentValues(android.content.ContentValues) ContentProviderOperation(android.content.ContentProviderOperation) PhoneLookupInfo(com.android.dialer.phonelookup.PhoneLookupInfo) ArrayList(java.util.ArrayList) DialerPhoneNumber(com.android.dialer.DialerPhoneNumber) MainThread(android.support.annotation.MainThread)

Example 8 with DialerPhoneNumber

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);
    }
}
Also used : ContentValues(android.content.ContentValues) ContentProviderOperation(android.content.ContentProviderOperation) NumberAttributes(com.android.dialer.NumberAttributes) Context(android.content.Context) LogUtil(com.android.dialer.common.LogUtil) Arrays(java.util.Arrays) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) AnnotatedCallLog(com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog) RemoteException(android.os.RemoteException) CallLogMutations(com.android.dialer.calllog.datasources.CallLogMutations) ArrayList(java.util.ArrayList) Inject(javax.inject.Inject) VisibleForTesting(android.support.annotation.VisibleForTesting) BackgroundExecutor(com.android.dialer.common.concurrent.Annotations.BackgroundExecutor) ProtoParsers(com.android.dialer.protos.ProtoParsers) ApplicationContext(com.android.dialer.inject.ApplicationContext) CallLog(android.provider.CallLog) Phone(android.provider.ContactsContract.CommonDataKinds.Phone) DialerPhoneNumber(com.android.dialer.DialerPhoneNumber) OperationApplicationException(android.content.OperationApplicationException) Futures(com.google.common.util.concurrent.Futures) Stream(java.util.stream.Stream) Calls(android.provider.CallLog.Calls) ContentValues(android.content.ContentValues) ContentUris(android.content.ContentUris) ListeningExecutorService(com.google.common.util.concurrent.ListeningExecutorService) ContentProviderOperation(android.content.ContentProviderOperation) ArrayList(java.util.ArrayList) DialerPhoneNumber(com.android.dialer.DialerPhoneNumber) RemoteException(android.os.RemoteException) NumberAttributes(com.android.dialer.NumberAttributes) OperationApplicationException(android.content.OperationApplicationException)

Example 9 with DialerPhoneNumber

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());
}
Also used : DialerPhoneNumber(com.android.dialer.DialerPhoneNumber) ListeningExecutorService(com.google.common.util.concurrent.ListeningExecutorService) DialerPhoneNumberUtil(com.android.dialer.phonenumberproto.DialerPhoneNumberUtil)

Example 10 with DialerPhoneNumber

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

Aggregations

DialerPhoneNumber (com.android.dialer.DialerPhoneNumber)26 InvalidProtocolBufferException (com.google.protobuf.InvalidProtocolBufferException)8 ContentValues (android.content.ContentValues)7 Cursor (android.database.Cursor)7 ImmutableMap (com.google.common.collect.ImmutableMap)7 ArrayList (java.util.ArrayList)7 ArraySet (android.support.v4.util.ArraySet)6 PhoneLookupInfo (com.android.dialer.phonelookup.PhoneLookupInfo)6 Cp2ContactInfo (com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info.Cp2ContactInfo)6 ImmutableSet (com.google.common.collect.ImmutableSet)6 ListenableFuture (com.google.common.util.concurrent.ListenableFuture)6 Set (java.util.Set)6 PartitionedNumbers (com.android.dialer.phonenumberproto.PartitionedNumbers)5 ListeningExecutorService (com.google.common.util.concurrent.ListeningExecutorService)5 Context (android.content.Context)4 ArraySet (android.util.ArraySet)4 LogUtil (com.android.dialer.common.LogUtil)4 BackgroundExecutor (com.android.dialer.common.concurrent.Annotations.BackgroundExecutor)4 ApplicationContext (com.android.dialer.inject.ApplicationContext)4 PhoneLookup (com.android.dialer.phonelookup.PhoneLookup)4