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.support.annotation.VisibleForTesting;
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.dialer.compat.telephony.TelephonyManagerCompat;
36 import com.android.dialer.storage.StorageComponent;
37 import com.android.voicemail.VoicemailClient;
38 import com.android.voicemail.VoicemailComponent;
39 
40 /**
41  * Receives {@link TelephonyManager#ACTION_SHOW_VOICEMAIL_NOTIFICATION}, and forwards to {@link
42  * LegacyVoicemailNotifier}. Will ignore the notification if the account has visual voicemail.
43  * Legacy voicemail is the traditional, non-visual, dial-in voicemail.
44  */
45 @TargetApi(VERSION_CODES.O)
46 public class LegacyVoicemailNotificationReceiver extends BroadcastReceiver {
47 
48   @VisibleForTesting static final String LEGACY_VOICEMAIL_DISMISSED = "legacy_voicemail_dismissed";
49 
50   @Override
onReceive(Context context, Intent intent)51   public void onReceive(Context context, Intent intent) {
52 
53     if (!TelephonyManager.ACTION_SHOW_VOICEMAIL_NOTIFICATION.equals(intent.getAction())
54         && !VoicemailClient.ACTION_SHOW_LEGACY_VOICEMAIL.equals(intent.getAction())) {
55       return;
56     }
57 
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     boolean isRefresh = intent.getBooleanExtra(TelephonyManagerCompat.EXTRA_IS_REFRESH, false);
77     LogUtil.i("LegacyVoicemailNotificationReceiver.onReceive", "isRefresh: " + isRefresh);
78     PerAccountSharedPreferences preferences = getSharedPreferences(context, phoneAccountHandle);
79     if (isRefresh) {
80       if (preferences.getBoolean(LEGACY_VOICEMAIL_DISMISSED, false)) {
81         LogUtil.i(
82             "LegacyVoicemailNotificationReceiver.onReceive",
83             "notification dismissed, ignoring refresh");
84         return;
85       }
86     } else {
87       setDismissed(context, phoneAccountHandle, false);
88     }
89 
90     if (count == -1) {
91       // Carrier might not send voicemail count. Missing extra means there are unknown numbers of
92       // voicemails (One or more). Treat it as 1 so the generic version will be shown. ("Voicemail"
93       // instead of "X voicemails")
94       count = 1;
95     }
96 
97     if (count == 0) {
98       LogUtil.i("LegacyVoicemailNotificationReceiver.onReceive", "clearing notification");
99       LegacyVoicemailNotifier.cancelNotification(context, phoneAccountHandle);
100       return;
101     }
102 
103     if (!intent.getBooleanExtra(VoicemailClient.EXTRA_IS_LEGACY_MODE, false)
104         && UserManagerCompat.isUserUnlocked(context)
105         && VoicemailComponent.get(context)
106             .getVoicemailClient()
107             .isActivated(context, phoneAccountHandle)) {
108       LogUtil.i(
109           "LegacyVoicemailNotificationReceiver.onReceive",
110           "visual voicemail is activated, ignoring notification");
111       return;
112     }
113 
114     String voicemailNumber = intent.getStringExtra(TelephonyManager.EXTRA_VOICEMAIL_NUMBER);
115     PendingIntent callVoicemailIntent =
116         intent.getParcelableExtra(TelephonyManager.EXTRA_CALL_VOICEMAIL_INTENT);
117     PendingIntent voicemailSettingIntent =
118         intent.getParcelableExtra(TelephonyManager.EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT);
119 
120     LogUtil.i("LegacyVoicemailNotificationReceiver.onReceive", "sending notification");
121     LegacyVoicemailNotifier.showNotification(
122         context,
123         phoneAccountHandle,
124         count,
125         voicemailNumber,
126         callVoicemailIntent,
127         voicemailSettingIntent,
128         isRefresh);
129   }
130 
setDismissed( Context context, PhoneAccountHandle phoneAccountHandle, boolean dismissed)131   public static void setDismissed(
132       Context context, PhoneAccountHandle phoneAccountHandle, boolean dismissed) {
133     getSharedPreferences(context, phoneAccountHandle)
134         .edit()
135         .putBoolean(LEGACY_VOICEMAIL_DISMISSED, dismissed)
136         .apply();
137   }
138 
139   @VisibleForTesting
getSharedPreferences( Context context, PhoneAccountHandle phoneAccountHandle)140   static PerAccountSharedPreferences getSharedPreferences(
141       Context context, PhoneAccountHandle phoneAccountHandle) {
142     return new PerAccountSharedPreferences(
143         context, phoneAccountHandle, StorageComponent.get(context).unencryptedSharedPrefs());
144   }
145 }
146