diff options
Diffstat (limited to 'java/com/android/dialer/app/calllog/DefaultVoicemailNotifier.java')
-rw-r--r-- | java/com/android/dialer/app/calllog/DefaultVoicemailNotifier.java | 446 |
1 files changed, 0 insertions, 446 deletions
diff --git a/java/com/android/dialer/app/calllog/DefaultVoicemailNotifier.java b/java/com/android/dialer/app/calllog/DefaultVoicemailNotifier.java deleted file mode 100644 index 58fe6fa2c..000000000 --- a/java/com/android/dialer/app/calllog/DefaultVoicemailNotifier.java +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.dialer.app.calllog; - -import android.annotation.TargetApi; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; -import android.os.PersistableBundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.VisibleForTesting; -import android.support.annotation.WorkerThread; -import android.support.v4.os.BuildCompat; -import android.support.v4.util.Pair; -import android.telecom.PhoneAccount; -import android.telecom.PhoneAccountHandle; -import android.telecom.TelecomManager; -import android.telephony.CarrierConfigManager; -import android.telephony.PhoneNumberUtils; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.ArrayMap; -import com.android.contacts.common.compat.TelephonyManagerCompat; -import com.android.contacts.common.util.ContactDisplayUtils; -import com.android.dialer.app.DialtactsActivity; -import com.android.dialer.app.R; -import com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall; -import com.android.dialer.app.contactinfo.ContactPhotoLoader; -import com.android.dialer.app.list.DialtactsPagerAdapter; -import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; -import com.android.dialer.blocking.FilteredNumbersUtil; -import com.android.dialer.calllogutils.PhoneAccountUtils; -import com.android.dialer.common.Assert; -import com.android.dialer.common.LogUtil; -import com.android.dialer.common.concurrent.DialerExecutor.Worker; -import com.android.dialer.common.concurrent.DialerExecutors; -import com.android.dialer.logging.DialerImpression; -import com.android.dialer.logging.Logger; -import com.android.dialer.notification.NotificationChannelManager; -import com.android.dialer.notification.NotificationChannelManager.Channel; -import com.android.dialer.phonenumbercache.ContactInfo; -import com.android.dialer.telecom.TelecomUtil; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -/** Shows a voicemail notification in the status bar. */ -public class DefaultVoicemailNotifier implements Worker<Void, Void> { - - public static final String TAG = "VoicemailNotifier"; - - /** The tag used to identify notifications from this class. */ - static final String VISUAL_VOICEMAIL_NOTIFICATION_TAG = "DefaultVoicemailNotifier"; - /** The identifier of the notification of new voicemails. */ - private static final int VISUAL_VOICEMAIL_NOTIFICATION_ID = R.id.notification_visual_voicemail; - - private static final int LEGACY_VOICEMAIL_NOTIFICATION_ID = R.id.notification_legacy_voicemail; - private static final String LEGACY_VOICEMAIL_NOTIFICATION_TAG = "legacy_voicemail"; - - private final Context context; - private final CallLogNotificationsQueryHelper queryHelper; - private final FilteredNumberAsyncQueryHandler filteredNumberAsyncQueryHandler; - - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - DefaultVoicemailNotifier( - Context context, - CallLogNotificationsQueryHelper queryHelper, - FilteredNumberAsyncQueryHandler filteredNumberAsyncQueryHandler) { - this.context = context; - this.queryHelper = queryHelper; - this.filteredNumberAsyncQueryHandler = filteredNumberAsyncQueryHandler; - } - - public DefaultVoicemailNotifier(Context context) { - this( - context, - CallLogNotificationsQueryHelper.getInstance(context), - new FilteredNumberAsyncQueryHandler(context)); - } - - @Nullable - @Override - public Void doInBackground(@Nullable Void input) throws Throwable { - updateNotification(); - return null; - } - - /** - * 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. - * - * <p>It is not safe to call this method from the main thread. - */ - @VisibleForTesting - @WorkerThread - void updateNotification() { - Assert.isWorkerThread(); - // Lookup the list of new voicemails to include in the notification. - final List<NewCall> newCalls = queryHelper.getNewVoicemails(); - - if (newCalls == null) { - // Query failed, just return. - return; - } - - Resources resources = context.getResources(); - - // 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. - final Map<String, ContactInfo> contactInfos = new ArrayMap<>(); - - // Iterate over the new voicemails to determine all the information above. - Iterator<NewCall> itr = newCalls.iterator(); - while (itr.hasNext()) { - NewCall newCall = itr.next(); - - // Skip notifying for numbers which are blocked. - if (!FilteredNumbersUtil.hasRecentEmergencyCall(context) - && filteredNumberAsyncQueryHandler.getBlockedIdSynchronous( - newCall.number, newCall.countryIso) - != null) { - itr.remove(); - - if (newCall.voicemailUri != null) { - // Delete the voicemail. - CallLogAsyncTaskUtil.deleteVoicemailSynchronous(context, newCall.voicemailUri); - } - continue; - } - - // Check if we already know the name associated with this number. - ContactInfo contactInfo = contactInfos.get(newCall.number); - if (contactInfo == null) { - 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 = - resources.getString( - R.string.notification_voicemail_callers_list, callers, contactInfo.name); - } - } - } - - if (newCalls.isEmpty()) { - // No voicemails to notify about - return; - } - - Notification.Builder groupSummary = - createNotificationBuilder() - .setContentTitle( - resources.getQuantityString( - R.plurals.notification_voicemail_title, newCalls.size(), newCalls.size())) - .setContentText(callers) - .setDeleteIntent(createMarkNewVoicemailsAsOldIntent(null)) - .setGroupSummary(true) - .setContentIntent(newVoicemailIntent(null)); - - if (BuildCompat.isAtLeastO()) { - groupSummary.setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN); - } - - NotificationChannelManager.applyChannel( - groupSummary, - context, - Channel.VOICEMAIL, - PhoneAccountHandles.getAccount(context, newCalls.get(0))); - - LogUtil.i(TAG, "Creating visual voicemail notification"); - getNotificationManager() - .notify( - VISUAL_VOICEMAIL_NOTIFICATION_TAG, - VISUAL_VOICEMAIL_NOTIFICATION_ID, - groupSummary.build()); - - for (NewCall voicemail : newCalls) { - getNotificationManager() - .notify( - voicemail.callsUri.toString(), - VISUAL_VOICEMAIL_NOTIFICATION_ID, - createNotificationForVoicemail(voicemail, contactInfos)); - } - } - - /** - * Replicates how packages/services/Telephony/NotificationMgr.java handles legacy voicemail - * notification. The notification will not be stackable because no information is available for - * individual voicemails. - */ - @TargetApi(VERSION_CODES.O) - public void notifyLegacyVoicemail( - @NonNull PhoneAccountHandle phoneAccountHandle, - int count, - String voicemailNumber, - PendingIntent callVoicemailIntent, - PendingIntent voicemailSettingIntent) { - Assert.isNotNull(phoneAccountHandle); - Assert.checkArgument(BuildCompat.isAtLeastO()); - TelephonyManager telephonyManager = - context - .getSystemService(TelephonyManager.class) - .createForPhoneAccountHandle(phoneAccountHandle); - Assert.isNotNull(telephonyManager); - LogUtil.i(TAG, "Creating legacy voicemail notification"); - - PersistableBundle carrierConfig = telephonyManager.getCarrierConfig(); - - String notificationTitle = - context - .getResources() - .getQuantityString(R.plurals.notification_voicemail_title, count, count); - - TelecomManager telecomManager = context.getSystemService(TelecomManager.class); - PhoneAccount phoneAccount = telecomManager.getPhoneAccount(phoneAccountHandle); - - String notificationText; - PendingIntent pendingIntent; - - if (voicemailSettingIntent != null) { - // If the voicemail number if unknown, instead of calling voicemail, take the user - // to the voicemail settings. - notificationText = context.getString(R.string.notification_voicemail_no_vm_number); - pendingIntent = voicemailSettingIntent; - } else { - if (PhoneAccountUtils.getSubscriptionPhoneAccounts(context).size() > 1) { - notificationText = phoneAccount.getShortDescription().toString(); - } else { - notificationText = - String.format( - context.getString(R.string.notification_voicemail_text_format), - PhoneNumberUtils.formatNumber(voicemailNumber)); - } - pendingIntent = callVoicemailIntent; - } - Notification.Builder builder = new Notification.Builder(context); - builder - .setSmallIcon(android.R.drawable.stat_notify_voicemail) - .setColor(context.getColor(R.color.dialer_theme_color)) - .setWhen(System.currentTimeMillis()) - .setContentTitle(notificationTitle) - .setContentText(notificationText) - .setContentIntent(pendingIntent) - .setSound(telephonyManager.getVoicemailRingtoneUri(phoneAccountHandle)) - .setOngoing( - carrierConfig.getBoolean( - CarrierConfigManager.KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL)); - - if (telephonyManager.isVoicemailVibrationEnabled(phoneAccountHandle)) { - builder.setDefaults(Notification.DEFAULT_VIBRATE); - } - - NotificationChannelManager.applyChannel( - builder, context, Channel.VOICEMAIL, phoneAccountHandle); - Notification notification = builder.build(); - getNotificationManager() - .notify(LEGACY_VOICEMAIL_NOTIFICATION_TAG, LEGACY_VOICEMAIL_NOTIFICATION_ID, notification); - } - - public void cancelLegacyNotification() { - LogUtil.i(TAG, "Clearing legacy voicemail notification"); - getNotificationManager() - .cancel(LEGACY_VOICEMAIL_NOTIFICATION_TAG, LEGACY_VOICEMAIL_NOTIFICATION_ID); - } - - /** - * Determines which ringtone Uri and Notification defaults to use when updating the notification - * for the given call. - */ - private Pair<Uri, Integer> getNotificationInfo(@Nullable NewCall callToNotify) { - LogUtil.v(TAG, "getNotificationInfo"); - if (callToNotify == null) { - LogUtil.i(TAG, "callToNotify == null"); - return new Pair<>(null, 0); - } - PhoneAccountHandle accountHandle = PhoneAccountHandles.getAccount(context, callToNotify); - if (accountHandle == null) { - LogUtil.i(TAG, "No default phone account found, using default notification ringtone"); - return new Pair<>(null, Notification.DEFAULT_ALL); - } - return new Pair<>( - TelephonyManagerCompat.getVoicemailRingtoneUri(getTelephonyManager(), accountHandle), - getNotificationDefaults(accountHandle)); - } - - private int getNotificationDefaults(PhoneAccountHandle accountHandle) { - if (VERSION.SDK_INT >= VERSION_CODES.N) { - return TelephonyManagerCompat.isVoicemailVibrationEnabled( - getTelephonyManager(), accountHandle) - ? Notification.DEFAULT_VIBRATE - : 0; - } - return Notification.DEFAULT_ALL; - } - - /** Creates a pending intent that marks all new voicemails as old. */ - private PendingIntent createMarkNewVoicemailsAsOldIntent(@Nullable Uri voicemailUri) { - Intent intent = new Intent(context, CallLogNotificationsService.class); - intent.setAction(CallLogNotificationsService.ACTION_MARK_NEW_VOICEMAILS_AS_OLD); - intent.setData(voicemailUri); - return PendingIntent.getService(context, 0, intent, 0); - } - - private NotificationManager getNotificationManager() { - return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - } - - private TelephonyManager getTelephonyManager() { - return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - } - - private Notification createNotificationForVoicemail( - @NonNull NewCall voicemail, @NonNull Map<String, ContactInfo> contactInfos) { - Pair<Uri, Integer> notificationInfo = getNotificationInfo(voicemail); - ContactInfo contactInfo = contactInfos.get(voicemail.number); - - Notification.Builder notificationBuilder = - createNotificationBuilder() - .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(notificationInfo.first) - .setDefaults(notificationInfo.second); - - if (voicemail.voicemailUri != null) { - notificationBuilder.setDeleteIntent( - createMarkNewVoicemailsAsOldIntent(voicemail.voicemailUri)); - } - - NotificationChannelManager.applyChannel( - notificationBuilder, - context, - Channel.VOICEMAIL, - PhoneAccountHandles.getAccount(context, voicemail)); - - ContactPhotoLoader loader = new ContactPhotoLoader(context, contactInfo); - Bitmap photoIcon = loader.loadPhotoIcon(); - if (photoIcon != null) { - notificationBuilder.setLargeIcon(photoIcon); - } - if (!TextUtils.isEmpty(voicemail.transcription)) { - Logger.get(context) - .logImpression(DialerImpression.Type.VVM_NOTIFICATION_CREATED_WITH_TRANSCRIPTION); - notificationBuilder.setStyle( - new Notification.BigTextStyle().bigText(voicemail.transcription)); - } - notificationBuilder.setContentIntent(newVoicemailIntent(voicemail)); - Logger.get(context).logImpression(DialerImpression.Type.VVM_NOTIFICATION_CREATED); - return notificationBuilder.build(); - } - - private Notification.Builder createNotificationBuilder() { - return new Notification.Builder(context) - .setSmallIcon(android.R.drawable.stat_notify_voicemail) - .setColor(context.getColor(R.color.dialer_theme_color)) - .setGroup(VISUAL_VOICEMAIL_NOTIFICATION_TAG) - .setOnlyAlertOnce(true) - .setAutoCancel(true); - } - - private PendingIntent newVoicemailIntent(@Nullable NewCall voicemail) { - Intent intent = - DialtactsActivity.getShowTabIntent(context, DialtactsPagerAdapter.TAB_INDEX_VOICEMAIL); - // TODO (b/35486204): scroll to this voicemail - if (voicemail != null) { - intent.setData(voicemail.voicemailUri); - } - intent.putExtra(DialtactsActivity.EXTRA_CLEAR_NEW_VOICEMAILS, true); - return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); - } - - /** - * Updates the voicemail notifications displayed. - * - * @param runnable Called when the async update task completes no matter if it succeeds or fails. - * May be null. - */ - static void updateVoicemailNotifications(Context context, Runnable runnable) { - if (!TelecomUtil.isDefaultDialer(context)) { - LogUtil.i( - "DefaultVoicemailNotifier.updateVoicemailNotifications", - "not default dialer, not scheduling update to voicemail notifications"); - return; - } - - DialerExecutors.createNonUiTaskBuilder(new DefaultVoicemailNotifier(context)) - .onSuccess( - output -> { - LogUtil.i( - "DefaultVoicemailNotifier.updateVoicemailNotifications", - "update voicemail notifications successful"); - if (runnable != null) { - runnable.run(); - } - }) - .onFailure( - throwable -> { - LogUtil.i( - "DefaultVoicemailNotifier.updateVoicemailNotifications", - "update voicemail notifications failed"); - if (runnable != null) { - runnable.run(); - } - }) - .build() - .executeParallel(null); - } -} |