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.voicemail; 18 19 import android.annotation.TargetApi; 20 import android.app.PendingIntent; 21 import android.content.BroadcastReceiver; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.os.Build; 25 import android.os.Build.VERSION_CODES; 26 import android.preference.PreferenceManager; 27 import android.support.v4.os.BuildCompat; 28 import android.support.v4.os.UserManagerCompat; 29 import android.telecom.PhoneAccountHandle; 30 import android.telephony.TelephonyManager; 31 import com.android.dialer.app.calllog.LegacyVoicemailNotifier; 32 import com.android.dialer.common.Assert; 33 import com.android.dialer.common.LogUtil; 34 import com.android.dialer.common.PerAccountSharedPreferences; 35 import com.android.voicemail.VoicemailComponent; 36 37 /** 38 * Receives {@link TelephonyManager#ACTION_SHOW_VOICEMAIL_NOTIFICATION}, and forwards to {@link 39 * LegacyVoicemailNotifier}. Will ignore the notification if the account has visual voicemail. 40 * Legacy voicemail is the traditional, non-visual, dial-in voicemail. 41 */ 42 @TargetApi(VERSION_CODES.O) 43 public class LegacyVoicemailNotificationReceiver extends BroadcastReceiver { 44 45 private static final String LEGACY_VOICEMAIL_COUNT = "legacy_voicemail_count"; 46 47 /** 48 * Hidden extra for {@link TelephonyManager#ACTION_SHOW_VOICEMAIL_NOTIFICATION} for whether the 49 * notification is just a refresh or for a new voicemail. The phone should not play a ringtone or 50 * vibrate during a refresh if the notification is already showing. 51 * 52 * <p>TODO(b/62202833): make public 53 */ 54 private static final String EXTRA_IS_REFRESH = "is_refresh"; 55 56 @Override 57 public void onReceive(Context context, Intent intent) { 58 LogUtil.i( 59 "LegacyVoicemailNotificationReceiver.onReceive", "received legacy voicemail notification"); 60 if (!BuildCompat.isAtLeastO()) { 61 LogUtil.e( 62 "LegacyVoicemailNotificationReceiver.onReceive", 63 "SDK not finalized: SDK_INT=" 64 + Build.VERSION.SDK_INT 65 + ", PREVIEW_SDK_INT=" 66 + Build.VERSION.PREVIEW_SDK_INT 67 + ", RELEASE=" 68 + Build.VERSION.RELEASE); 69 return; 70 } 71 72 PhoneAccountHandle phoneAccountHandle = 73 Assert.isNotNull(intent.getParcelableExtra(TelephonyManager.EXTRA_PHONE_ACCOUNT_HANDLE)); 74 int count = intent.getIntExtra(TelephonyManager.EXTRA_NOTIFICATION_COUNT, -1); 75 76 if (!hasVoicemailCountChanged(context, phoneAccountHandle, count)) { 77 LogUtil.i( 78 "LegacyVoicemailNotificationReceiver.onReceive", 79 "voicemail count hasn't changed, ignoring"); 80 return; 81 } 82 83 if (count == -1) { 84 // Carrier might not send voicemail count. Missing extra means there are unknown numbers of 85 // voicemails (One or more). Treat it as 1 so the generic version will be shown. ("Voicemail" 86 // instead of "X voicemails") 87 count = 1; 88 } 89 90 if (count == 0) { 91 LogUtil.i("LegacyVoicemailNotificationReceiver.onReceive", "clearing notification"); 92 LegacyVoicemailNotifier.cancelNotification(context); 93 return; 94 } 95 96 if (VoicemailComponent.get(context) 97 .getVoicemailClient() 98 .isActivated(context, phoneAccountHandle)) { 99 LogUtil.i( 100 "LegacyVoicemailNotificationReceiver.onReceive", 101 "visual voicemail is activated, ignoring notification"); 102 return; 103 } 104 105 String voicemailNumber = intent.getStringExtra(TelephonyManager.EXTRA_VOICEMAIL_NUMBER); 106 PendingIntent callVoicemailIntent = 107 intent.getParcelableExtra(TelephonyManager.EXTRA_CALL_VOICEMAIL_INTENT); 108 PendingIntent voicemailSettingIntent = 109 intent.getParcelableExtra(TelephonyManager.EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT); 110 111 LogUtil.i("LegacyVoicemailNotificationReceiver.onReceive", "sending notification"); 112 LegacyVoicemailNotifier.showNotification( 113 context, 114 phoneAccountHandle, 115 count, 116 voicemailNumber, 117 callVoicemailIntent, 118 voicemailSettingIntent, 119 intent.getBooleanExtra(EXTRA_IS_REFRESH, false)); 120 } 121 122 private static boolean hasVoicemailCountChanged( 123 Context context, PhoneAccountHandle phoneAccountHandle, int newCount) { 124 // Need credential encrypted storage to access preferences. 125 if (!UserManagerCompat.isUserUnlocked(context)) { 126 LogUtil.i( 127 "LegacyVoicemailNotificationReceiver.onReceive", 128 "User locked, bypassing voicemail count check"); 129 return true; 130 } 131 132 if (newCount == -1) { 133 // Carrier does not report voicemail count 134 return true; 135 } 136 137 PerAccountSharedPreferences preferences = 138 new PerAccountSharedPreferences( 139 context, phoneAccountHandle, PreferenceManager.getDefaultSharedPreferences(context)); 140 // Carriers may send multiple notifications for the same voicemail. 141 if (newCount != 0 && newCount == preferences.getInt(LEGACY_VOICEMAIL_COUNT, -1)) { 142 return false; 143 } 144 preferences.edit().putInt(LEGACY_VOICEMAIL_COUNT, newCount).apply(); 145 return true; 146 } 147 } 148