1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.dialer.app.calllog; 18 19 import android.annotation.TargetApi; 20 import android.app.Notification; 21 import android.app.PendingIntent; 22 import android.content.Context; 23 import android.os.Build.VERSION_CODES; 24 import android.os.PersistableBundle; 25 import android.support.annotation.NonNull; 26 import android.support.v4.os.BuildCompat; 27 import android.telecom.PhoneAccount; 28 import android.telecom.PhoneAccountHandle; 29 import android.telecom.TelecomManager; 30 import android.telephony.CarrierConfigManager; 31 import android.telephony.TelephonyManager; 32 import android.text.TextUtils; 33 import com.android.dialer.app.R; 34 import com.android.dialer.common.Assert; 35 import com.android.dialer.common.LogUtil; 36 import com.android.dialer.location.GeoUtil; 37 import com.android.dialer.notification.DialerNotificationManager; 38 import com.android.dialer.notification.NotificationChannelManager; 39 import com.android.dialer.notification.VoicemailChannelUtils; 40 import com.android.dialer.phonenumberutil.PhoneNumberHelper; 41 import com.android.dialer.telecom.TelecomUtil; 42 import com.android.dialer.theme.base.ThemeComponent; 43 44 /** Shows a notification in the status bar for legacy vociemail. */ 45 @TargetApi(VERSION_CODES.O) 46 public final class LegacyVoicemailNotifier { 47 private static final String NOTIFICATION_TAG_PREFIX = "LegacyVoicemail_"; 48 private static final String NOTIFICATION_TAG = "LegacyVoicemail"; 49 private static final int NOTIFICATION_ID = 1; 50 51 /** 52 * Replicates how packages/services/Telephony/NotificationMgr.java handles legacy voicemail 53 * notification. The notification will not be stackable because no information is available for 54 * individual voicemails. 55 */ showNotification( @onNull Context context, @NonNull PhoneAccountHandle handle, int count, String voicemailNumber, PendingIntent callVoicemailIntent, PendingIntent voicemailSettingsIntent, boolean isRefresh)56 public static void showNotification( 57 @NonNull Context context, 58 @NonNull PhoneAccountHandle handle, 59 int count, 60 String voicemailNumber, 61 PendingIntent callVoicemailIntent, 62 PendingIntent voicemailSettingsIntent, 63 boolean isRefresh) { 64 LogUtil.enterBlock("LegacyVoicemailNotifier.showNotification"); 65 Assert.isNotNull(handle); 66 Assert.checkArgument(BuildCompat.isAtLeastO()); 67 68 TelephonyManager pinnedTelephonyManager = 69 context.getSystemService(TelephonyManager.class).createForPhoneAccountHandle(handle); 70 if (pinnedTelephonyManager == null) { 71 LogUtil.e("LegacyVoicemailNotifier.showNotification", "invalid PhoneAccountHandle"); 72 return; 73 } 74 75 Notification notification = 76 createNotification( 77 context, 78 pinnedTelephonyManager, 79 handle, 80 count, 81 voicemailNumber, 82 callVoicemailIntent, 83 voicemailSettingsIntent, 84 isRefresh); 85 DialerNotificationManager.notify( 86 context, getNotificationTag(context, handle), NOTIFICATION_ID, notification); 87 } 88 89 @NonNull createNotification( @onNull Context context, @NonNull TelephonyManager pinnedTelephonyManager, @NonNull PhoneAccountHandle handle, int count, String voicemailNumber, PendingIntent callVoicemailIntent, PendingIntent voicemailSettingsIntent, boolean isRefresh)90 private static Notification createNotification( 91 @NonNull Context context, 92 @NonNull TelephonyManager pinnedTelephonyManager, 93 @NonNull PhoneAccountHandle handle, 94 int count, 95 String voicemailNumber, 96 PendingIntent callVoicemailIntent, 97 PendingIntent voicemailSettingsIntent, 98 boolean isRefresh) { 99 String notificationTitle = 100 context 101 .getResources() 102 .getQuantityString(R.plurals.notification_voicemail_title, count, count); 103 PersistableBundle config = pinnedTelephonyManager.getCarrierConfig(); 104 boolean isOngoing; 105 if (config == null) { 106 isOngoing = false; 107 } else { 108 isOngoing = 109 config.getBoolean(CarrierConfigManager.KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL); 110 } 111 String contentText; 112 PendingIntent contentIntent; 113 if (!TextUtils.isEmpty(voicemailNumber) && callVoicemailIntent != null) { 114 contentText = getNotificationText(context, handle, voicemailNumber); 115 contentIntent = callVoicemailIntent; 116 } else { 117 contentText = context.getString(R.string.notification_voicemail_no_vm_number); 118 contentIntent = voicemailSettingsIntent; 119 } 120 121 Notification.Builder builder = 122 new Notification.Builder(context) 123 .setSmallIcon(android.R.drawable.stat_notify_voicemail) 124 .setColor(ThemeComponent.get(context).theme().getColorPrimary()) 125 .setWhen(System.currentTimeMillis()) 126 .setContentTitle(notificationTitle) 127 .setContentText(contentText) 128 .setContentIntent(contentIntent) 129 .setSound(pinnedTelephonyManager.getVoicemailRingtoneUri(handle)) 130 .setOngoing(isOngoing) 131 .setOnlyAlertOnce(isRefresh) 132 .setChannelId(NotificationChannelManager.getVoicemailChannelId(context, handle)) 133 .setDeleteIntent( 134 CallLogNotificationsService.createLegacyVoicemailDismissedPendingIntent( 135 context, handle)); 136 137 if (pinnedTelephonyManager.isVoicemailVibrationEnabled(handle)) { 138 builder.setDefaults(Notification.DEFAULT_VIBRATE); 139 } 140 141 return builder.build(); 142 } 143 144 @NonNull getNotificationText( @onNull Context context, PhoneAccountHandle handle, String voicemailNumber)145 private static String getNotificationText( 146 @NonNull Context context, PhoneAccountHandle handle, String voicemailNumber) { 147 if (TelecomUtil.getCallCapablePhoneAccounts(context).size() > 1) { 148 TelecomManager telecomManager = context.getSystemService(TelecomManager.class); 149 PhoneAccount phoneAccount = telecomManager.getPhoneAccount(handle); 150 if (phoneAccount != null) { 151 return phoneAccount.getShortDescription().toString(); 152 } 153 } 154 return String.format( 155 context.getString(R.string.notification_voicemail_text_format), 156 PhoneNumberHelper.formatNumber( 157 context, voicemailNumber, GeoUtil.getCurrentCountryIso(context))); 158 } 159 cancelNotification( @onNull Context context, @NonNull PhoneAccountHandle phoneAccountHandle)160 public static void cancelNotification( 161 @NonNull Context context, @NonNull PhoneAccountHandle phoneAccountHandle) { 162 LogUtil.enterBlock("LegacyVoicemailNotifier.cancelNotification"); 163 Assert.checkArgument(BuildCompat.isAtLeastO()); 164 Assert.isNotNull(phoneAccountHandle); 165 if ("null".equals(phoneAccountHandle.getId())) { 166 // while PhoneAccountHandle itself will never be null, telephony may still construct a "null" 167 // handle if the SIM is no longer available. Usually both SIM will be removed at the sames 168 // time, so just clear all notifications. 169 LogUtil.i( 170 "LegacyVoicemailNotifier.cancelNotification", 171 "'null' id, canceling all legacy voicemail notifications"); 172 DialerNotificationManager.cancelAll(context, NOTIFICATION_TAG); 173 } else { 174 DialerNotificationManager.cancel( 175 context, getNotificationTag(context, phoneAccountHandle), NOTIFICATION_ID); 176 } 177 } 178 179 @NonNull getNotificationTag( @onNull Context context, @NonNull PhoneAccountHandle phoneAccountHandle)180 private static String getNotificationTag( 181 @NonNull Context context, @NonNull PhoneAccountHandle phoneAccountHandle) { 182 if (context.getSystemService(TelephonyManager.class).getPhoneCount() <= 1) { 183 return NOTIFICATION_TAG; 184 } 185 return NOTIFICATION_TAG_PREFIX 186 + VoicemailChannelUtils.getHashedPhoneAccountId(phoneAccountHandle); 187 } 188 LegacyVoicemailNotifier()189 private LegacyVoicemailNotifier() {} 190 } 191