Search in sources :

Example 6 with ContactInfo

use of com.android.dialer.phonenumbercache.ContactInfo in project android_packages_apps_Dialer by LineageOS.

the class CallLogAdapter method createPhoneCallDetails.

/**
 * Initialize PhoneCallDetails by reading all data from cursor. This method must be run on main
 * thread since cursor is not thread safe.
 */
@MainThread
private PhoneCallDetails createPhoneCallDetails(Cursor cursor, int count, final CallLogListItemViewHolder views) {
    Assert.isMainThread();
    final String number = cursor.getString(CallLogQuery.NUMBER);
    final String postDialDigits = (VERSION.SDK_INT >= VERSION_CODES.N) ? cursor.getString(CallLogQuery.POST_DIAL_DIGITS) : "";
    final String viaNumber = (VERSION.SDK_INT >= VERSION_CODES.N) ? cursor.getString(CallLogQuery.VIA_NUMBER) : "";
    final int numberPresentation = cursor.getInt(CallLogQuery.NUMBER_PRESENTATION);
    final ContactInfo cachedContactInfo = ContactInfoHelper.getContactInfo(cursor);
    final PhoneCallDetails details = new PhoneCallDetails(number, numberPresentation, postDialDigits);
    details.viaNumber = viaNumber;
    details.countryIso = cursor.getString(CallLogQuery.COUNTRY_ISO);
    details.date = cursor.getLong(CallLogQuery.DATE);
    details.duration = cursor.getLong(CallLogQuery.DURATION);
    details.features = getCallFeatures(cursor, count);
    details.geocode = cursor.getString(CallLogQuery.GEOCODED_LOCATION);
    details.transcription = cursor.getString(CallLogQuery.TRANSCRIPTION);
    details.callTypes = getCallTypes(cursor, count);
    details.accountComponentName = cursor.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME);
    details.accountId = cursor.getString(CallLogQuery.ACCOUNT_ID);
    details.cachedContactInfo = cachedContactInfo;
    if (!cursor.isNull(CallLogQuery.DATA_USAGE)) {
        details.dataUsage = cursor.getLong(CallLogQuery.DATA_USAGE);
    }
    views.rowId = cursor.getLong(CallLogQuery.ID);
    // Stash away the Ids of the calls so that we can support deleting a row in the call log.
    views.callIds = getCallIds(cursor, count);
    details.previousGroup = getPreviousDayGroup(cursor);
    // Store values used when the actions ViewStub is inflated on expansion.
    views.number = number;
    views.countryIso = details.countryIso;
    views.postDialDigits = details.postDialDigits;
    views.numberPresentation = numberPresentation;
    if (details.callTypes[0] == CallLog.Calls.VOICEMAIL_TYPE || details.callTypes[0] == CallLog.Calls.MISSED_TYPE) {
        details.isRead = cursor.getInt(CallLogQuery.IS_READ) == 1;
    }
    views.callType = cursor.getInt(CallLogQuery.CALL_TYPE);
    views.voicemailUri = cursor.getString(CallLogQuery.VOICEMAIL_URI);
    return details;
}
Also used : PhoneCallDetails(com.android.dialer.calllogutils.PhoneCallDetails) ContactInfo(com.android.dialer.phonenumbercache.ContactInfo) MainThread(android.support.annotation.MainThread)

Example 7 with ContactInfo

use of com.android.dialer.phonenumbercache.ContactInfo in project android_packages_apps_Dialer by LineageOS.

the class ContactInfoCache method queryContactInfo.

/**
 * Queries the appropriate content provider for the contact associated with the number.
 *
 * <p>Upon completion it also updates the cache in the call log, if it is different from {@code
 * callLogInfo}.
 *
 * <p>The number might be either a SIP address or a phone number.
 *
 * <p>It returns true if it updated the content of the cache and we should therefore tell the view
 * to update its content.
 */
private boolean queryContactInfo(ContactInfoRequest request) {
    LogUtil.d("ContactInfoCache.queryContactInfo", "request number: %s, type: %d", LogUtil.sanitizePhoneNumber(request.number), request.type);
    ContactInfo info;
    if (request.isLocalRequest()) {
        info = mContactInfoHelper.lookupNumber(request.number, request.countryIso);
        if (info != null && !info.contactExists) {
            // TODO: Maybe skip look up if it's already available in cached number lookup
            // service.
            long start = SystemClock.elapsedRealtime();
            mContactInfoHelper.updateFromCequintCallerId(mCequintCallerIdManager, info, request.number);
            long time = SystemClock.elapsedRealtime() - start;
            LogUtil.d("ContactInfoCache.queryContactInfo", "Cequint Caller Id look up takes %d ms", time);
        }
        if (request.type == ContactInfoRequest.TYPE_LOCAL_AND_REMOTE) {
            if (!mContactInfoHelper.hasName(info)) {
                enqueueRequest(request.number, request.countryIso, request.callLogInfo, true, ContactInfoRequest.TYPE_REMOTE);
                return false;
            }
        }
    } else {
        info = mContactInfoHelper.lookupNumberInRemoteDirectory(request.number, request.countryIso);
    }
    if (info == null) {
        // The lookup failed, just return without requesting to update the view.
        return false;
    }
    // Check the existing entry in the cache: only if it has changed we should update the
    // view.
    NumberWithCountryIso numberCountryIso = new NumberWithCountryIso(request.number, request.countryIso);
    ContactInfo existingInfo = mCache.getPossiblyExpired(numberCountryIso);
    final boolean isRemoteSource = info.sourceType != Type.UNKNOWN_SOURCE_TYPE;
    // Don't force redraw if existing info in the cache is equal to {@link ContactInfo#EMPTY}
    // to avoid updating the data set for every new row that is scrolled into view.
    // Exception: Photo uris for contacts from remote sources are not cached in the call log
    // cache, so we have to force a redraw for these contacts regardless.
    boolean updated = (!Objects.equals(existingInfo, ContactInfo.EMPTY) || isRemoteSource) && !info.equals(existingInfo);
    // Store the data in the cache so that the UI thread can use to display it. Store it
    // even if it has not changed so that it is marked as not expired.
    mCache.put(numberCountryIso, info);
    // Update the call log even if the cache it is up-to-date: it is possible that the cache
    // contains the value from a different call log entry.
    mContactInfoHelper.updateCallLogContactInfo(request.number, request.countryIso, info, request.callLogInfo);
    if (!request.isLocalRequest()) {
        mContactInfoHelper.updateCachedNumberLookupService(info);
    }
    return updated;
}
Also used : ContactInfo(com.android.dialer.phonenumbercache.ContactInfo)

Example 8 with ContactInfo

use of com.android.dialer.phonenumbercache.ContactInfo in project android_packages_apps_Dialer by LineageOS.

the class MissedCallNotifier method updateMissedCallNotification.

/**
 * Update missed call notifications from the call log. Accepts default information in case call
 * log cannot be accessed.
 *
 * @param count the number of missed calls to display if call log cannot be accessed. May be
 *     {@link CallLogNotificationsService#UNKNOWN_MISSED_CALL_COUNT} if unknown.
 * @param number the phone number of the most recent call to display if the call log cannot be
 *     accessed. May be null if unknown.
 */
@VisibleForTesting
@WorkerThread
void updateMissedCallNotification(int count, @Nullable String number) {
    final int titleResId;
    // The text in the notification's line 1 and 2.
    CharSequence expandedText;
    List<NewCall> newCalls = callLogNotificationsQueryHelper.getNewMissedCalls();
    if ((newCalls != null && newCalls.isEmpty()) || count == 0) {
        // No calls to notify about: clear the notification.
        CallLogNotificationsQueryHelper.markAllMissedCallsInCallLogAsRead(context);
        cancelAllMissedCallNotifications(context);
        return;
    }
    if (newCalls != null) {
        if (count != CallLogNotificationsService.UNKNOWN_MISSED_CALL_COUNT && count != newCalls.size()) {
            LogUtil.w("MissedCallNotifier.updateMissedCallNotification", "Call count does not match call log count." + " count: " + count + " newCalls.size(): " + newCalls.size());
        }
        count = newCalls.size();
    }
    if (count == CallLogNotificationsService.UNKNOWN_MISSED_CALL_COUNT) {
        // call log, then no notification can be shown.
        return;
    }
    Notification.Builder groupSummary = createNotificationBuilder();
    boolean useCallList = newCalls != null;
    if (count == 1) {
        NewCall call = useCallList ? newCalls.get(0) : new NewCall(null, null, number, Calls.PRESENTATION_ALLOWED, null, null, null, null, System.currentTimeMillis());
        // TODO: look up caller ID that is not in contacts.
        ContactInfo contactInfo = callLogNotificationsQueryHelper.getContactInfo(call.number, call.numberPresentation, call.countryIso);
        titleResId = contactInfo.userType == ContactsUtils.USER_TYPE_WORK ? R.string.notification_missedWorkCallTitle : R.string.notification_missedCallTitle;
        if (TextUtils.equals(contactInfo.name, contactInfo.formattedNumber) || TextUtils.equals(contactInfo.name, contactInfo.number)) {
            expandedText = PhoneNumberUtilsCompat.createTtsSpannable(BidiFormatter.getInstance().unicodeWrap(contactInfo.name, TextDirectionHeuristics.LTR));
        } else {
            expandedText = contactInfo.name;
        }
        ContactPhotoLoader loader = new ContactPhotoLoader(context, contactInfo);
        Bitmap photoIcon = loader.loadPhotoIcon();
        if (photoIcon != null) {
            groupSummary.setLargeIcon(photoIcon);
        }
    } else {
        titleResId = R.string.notification_missedCallsTitle;
        expandedText = context.getString(R.string.notification_missedCallsMsg, count);
    }
    // Create a public viewable version of the notification, suitable for display when sensitive
    // notification content is hidden.
    Notification.Builder publicSummaryBuilder = createNotificationBuilder();
    publicSummaryBuilder.setContentTitle(context.getText(titleResId)).setContentIntent(createCallLogPendingIntent()).setDeleteIntent(CallLogNotificationsService.createCancelAllMissedCallsPendingIntent(context));
    // Create the notification summary suitable for display when sensitive information is showing.
    groupSummary.setContentTitle(context.getText(titleResId)).setContentText(expandedText).setContentIntent(createCallLogPendingIntent()).setDeleteIntent(CallLogNotificationsService.createCancelAllMissedCallsPendingIntent(context)).setGroupSummary(useCallList).setOnlyAlertOnce(useCallList).setPublicVersion(publicSummaryBuilder.build());
    if (BuildCompat.isAtLeastO()) {
        groupSummary.setChannelId(NotificationChannelId.MISSED_CALL);
    }
    Notification notification = groupSummary.build();
    configureLedOnNotification(notification);
    LogUtil.i("MissedCallNotifier.updateMissedCallNotification", "adding missed call notification");
    getNotificationMgr().notify(getNotificationTagForGroupSummary(), NOTIFICATION_ID, notification);
    if (useCallList) {
        // Do not repost active notifications to prevent erasing post call notes.
        NotificationManager manager = getNotificationMgr();
        Set<String> activeTags = new ArraySet<>();
        for (StatusBarNotification activeNotification : manager.getActiveNotifications()) {
            activeTags.add(activeNotification.getTag());
        }
        for (NewCall call : newCalls) {
            String callTag = getNotificationTagForCall(call);
            if (!activeTags.contains(callTag)) {
                manager.notify(callTag, NOTIFICATION_ID, getNotificationForCall(call, null));
            }
        }
    }
}
Also used : ArraySet(android.util.ArraySet) Builder(android.app.Notification.Builder) NotificationManager(android.app.NotificationManager) Notification(android.app.Notification) StatusBarNotification(android.service.notification.StatusBarNotification) NewCall(com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall) Bitmap(android.graphics.Bitmap) StatusBarNotification(android.service.notification.StatusBarNotification) ContactPhotoLoader(com.android.dialer.app.contactinfo.ContactPhotoLoader) ContactInfo(com.android.dialer.phonenumbercache.ContactInfo) VisibleForTesting(android.support.annotation.VisibleForTesting) WorkerThread(android.support.annotation.WorkerThread)

Example 9 with ContactInfo

use of com.android.dialer.phonenumbercache.ContactInfo in project android_packages_apps_Dialer by LineageOS.

the class VisualVoicemailNotifier method createNotificationForVoicemail.

private static Notification createNotificationForVoicemail(@NonNull Context context, @NonNull NewCall voicemail, @NonNull Map<String, ContactInfo> contactInfos) {
    PhoneAccountHandle handle = getAccountForCall(context, voicemail);
    ContactInfo contactInfo = contactInfos.get(voicemail.number);
    Notification.Builder builder = createNotificationBuilder(context).setContentTitle(context.getResources().getQuantityString(R.plurals.notification_voicemail_title, 1, 1)).setContentText(ContactDisplayUtils.getTtsSpannedPhoneNumber(context.getResources(), R.string.notification_new_voicemail_ticker, contactInfo.name)).setWhen(voicemail.dateMs).setSound(getVoicemailRingtoneUri(context, handle)).setDefaults(getNotificationDefaultFlags(context, handle));
    if (voicemail.voicemailUri != null) {
        builder.setDeleteIntent(CallLogNotificationsService.createMarkSingleNewVoicemailAsOldIntent(context, voicemail.voicemailUri));
    }
    if (BuildCompat.isAtLeastO()) {
        builder.setChannelId(NotificationChannelManager.getVoicemailChannelId(context, handle));
    }
    ContactPhotoLoader loader = new ContactPhotoLoader(context, contactInfo);
    Bitmap photoIcon = loader.loadPhotoIcon();
    if (photoIcon != null) {
        builder.setLargeIcon(photoIcon);
    }
    if (!TextUtils.isEmpty(voicemail.transcription)) {
        Logger.get(context).logImpression(DialerImpression.Type.VVM_NOTIFICATION_CREATED_WITH_TRANSCRIPTION);
        builder.setStyle(new Notification.BigTextStyle().bigText(voicemail.transcription));
    }
    builder.setContentIntent(newVoicemailIntent(context, voicemail));
    Logger.get(context).logImpression(DialerImpression.Type.VVM_NOTIFICATION_CREATED);
    return builder.build();
}
Also used : Bitmap(android.graphics.Bitmap) PhoneAccountHandle(android.telecom.PhoneAccountHandle) ContactPhotoLoader(com.android.dialer.app.contactinfo.ContactPhotoLoader) ContactInfo(com.android.dialer.phonenumbercache.ContactInfo) Notification(android.app.Notification) StatusBarNotification(android.service.notification.StatusBarNotification)

Example 10 with ContactInfo

use of com.android.dialer.phonenumbercache.ContactInfo in project android_packages_apps_Dialer by LineageOS.

the class VisualVoicemailUpdateTask method updateNotification.

/**
 * Updates the notification and notifies of the call with the given URI.
 *
 * <p>Clears the notification if there are no new voicemails, and notifies if the given URI
 * corresponds to a new voicemail.
 */
@WorkerThread
private static void updateNotification(Context context, CallLogNotificationsQueryHelper queryHelper, FilteredNumberAsyncQueryHandler queryHandler) {
    Assert.isWorkerThread();
    List<NewCall> newCalls = queryHelper.getNewVoicemails();
    if (newCalls == null) {
        return;
    }
    newCalls = filterBlockedNumbers(context, queryHandler, newCalls);
    if (newCalls.isEmpty()) {
        return;
    }
    // This represents a list of names to include in the notification.
    String callers = null;
    // Maps each number into a name: if a number is in the map, it has already left a more
    // recent voicemail.
    Map<String, ContactInfo> contactInfos = new ArrayMap<>();
    for (NewCall newCall : newCalls) {
        if (!contactInfos.containsKey(newCall.number)) {
            ContactInfo contactInfo = queryHelper.getContactInfo(newCall.number, newCall.numberPresentation, newCall.countryIso);
            contactInfos.put(newCall.number, contactInfo);
            // This is a new caller. Add it to the back of the list of callers.
            if (TextUtils.isEmpty(callers)) {
                callers = contactInfo.name;
            } else {
                callers = context.getString(R.string.notification_voicemail_callers_list, callers, contactInfo.name);
            }
        }
    }
    VisualVoicemailNotifier.showNotifications(context, newCalls, contactInfos, callers);
}
Also used : NewCall(com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall) ArrayMap(android.util.ArrayMap) ContactInfo(com.android.dialer.phonenumbercache.ContactInfo) WorkerThread(android.support.annotation.WorkerThread)

Aggregations

ContactInfo (com.android.dialer.phonenumbercache.ContactInfo)19 JSONException (org.json.JSONException)5 JSONObject (org.json.JSONObject)4 Notification (android.app.Notification)3 Cursor (android.database.Cursor)3 Bitmap (android.graphics.Bitmap)3 StatusBarNotification (android.service.notification.StatusBarNotification)3 WorkerThread (android.support.annotation.WorkerThread)3 ContactPhotoLoader (com.android.dialer.app.contactinfo.ContactPhotoLoader)3 ContactBuilder (com.android.dialer.lookup.ContactBuilder)3 CachedContactInfo (com.android.dialer.phonenumbercache.CachedNumberLookupService.CachedContactInfo)3 ArrayList (java.util.ArrayList)3 JSONArray (org.json.JSONArray)3 Builder (android.app.Notification.Builder)2 Uri (android.net.Uri)2 PhoneAccountHandle (android.telecom.PhoneAccountHandle)2 NewCall (com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall)2 NotificationManager (android.app.NotificationManager)1 MatrixCursor (android.database.MatrixCursor)1 MainThread (android.support.annotation.MainThread)1