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;
}
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;
}
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));
}
}
}
}
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();
}
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);
}
Aggregations