1 /*
2  * Copyright (C) 2016 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.voicemail.listui.error;
18 
19 import android.content.ComponentName;
20 import android.content.Context;
21 import android.database.Cursor;
22 import android.os.Build.VERSION;
23 import android.os.Build.VERSION_CODES;
24 import android.provider.VoicemailContract.Status;
25 import android.telecom.PhoneAccountHandle;
26 import android.telephony.TelephonyManager;
27 import com.android.dialer.common.Assert;
28 import com.android.dialer.common.LogUtil;
29 import com.android.dialer.compat.telephony.TelephonyManagerCompat;
30 import com.android.dialer.configprovider.ConfigProviderComponent;
31 import com.android.dialer.logging.DialerImpression;
32 import com.android.dialer.logging.Logger;
33 
34 /**
35  * This class will detect the corruption in the voicemail status and log it so we can track how many
36  * users are affected.
37  */
38 public class VoicemailStatusCorruptionHandler {
39 
40   /** Where the check is made so logging can be done. */
41   public enum Source {
42     Activity,
43     Notification
44   }
45 
46   private static final String CONFIG_VVM_STATUS_FIX_DISABLED = "vvm_status_fix_disabled";
47 
maybeFixVoicemailStatus(Context context, Cursor statusCursor, Source source)48   public static void maybeFixVoicemailStatus(Context context, Cursor statusCursor, Source source) {
49 
50     if (ConfigProviderComponent.get(context)
51         .getConfigProvider()
52         .getBoolean(CONFIG_VVM_STATUS_FIX_DISABLED, false)) {
53       return;
54     }
55 
56     if (VERSION.SDK_INT != VERSION_CODES.N_MR1) {
57       // This issue is specific to N MR1, it is fixed in future SDK.
58       return;
59     }
60 
61     if (statusCursor.getCount() == 0) {
62       return;
63     }
64 
65     statusCursor.moveToFirst();
66     VoicemailStatus status = new VoicemailStatus(context, statusCursor);
67     PhoneAccountHandle phoneAccountHandle =
68         new PhoneAccountHandle(
69             ComponentName.unflattenFromString(status.phoneAccountComponentName),
70             status.phoneAccountId);
71 
72     TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
73 
74     boolean visualVoicemailEnabled =
75         TelephonyManagerCompat.isVisualVoicemailEnabled(telephonyManager, phoneAccountHandle);
76     LogUtil.i(
77         "VoicemailStatusCorruptionHandler.maybeFixVoicemailStatus",
78         "Source="
79             + source
80             + ", CONFIGURATION_STATE="
81             + status.configurationState
82             + ", visualVoicemailEnabled="
83             + visualVoicemailEnabled);
84 
85     // If visual voicemail is enabled, the CONFIGURATION_STATE should be either OK, PIN_NOT_SET,
86     // or other failure code. CONFIGURATION_STATE_NOT_CONFIGURED means that the client has been
87     // shut down improperly (a bug). The client should be reset or the VVM tab will be
88     // missing.
89     if (Status.CONFIGURATION_STATE_NOT_CONFIGURED == status.configurationState
90         && visualVoicemailEnabled) {
91       LogUtil.e(
92           "VoicemailStatusCorruptionHandler.maybeFixVoicemailStatus",
93           "VVM3 voicemail status corrupted");
94 
95       switch (source) {
96         case Activity:
97           Logger.get(context)
98               .logImpression(
99                   DialerImpression.Type
100                       .VOICEMAIL_CONFIGURATION_STATE_CORRUPTION_DETECTED_FROM_ACTIVITY);
101           break;
102         case Notification:
103           Logger.get(context)
104               .logImpression(
105                   DialerImpression.Type
106                       .VOICEMAIL_CONFIGURATION_STATE_CORRUPTION_DETECTED_FROM_NOTIFICATION);
107           break;
108         default:
109           Assert.fail("this should never happen");
110           break;
111       }
112       // At this point we could attempt to work around the issue by disabling and re-enabling
113       // voicemail. Unfortunately this work around is buggy so we'll do nothing for now.
114     }
115   }
116 }
117