• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.phone.vvm.omtp.protocol;
18 
19 import android.annotation.IntDef;
20 import android.content.Context;
21 import android.provider.VoicemailContract.Status;
22 import android.telecom.PhoneAccountHandle;
23 import android.util.Log;
24 
25 import com.android.phone.VoicemailStatus;
26 import com.android.phone.settings.VoicemailChangePinActivity;
27 import com.android.phone.vvm.omtp.DefaultOmtpEventHandler;
28 import com.android.phone.vvm.omtp.OmtpEvents;
29 import com.android.phone.vvm.omtp.OmtpEvents.Type;
30 import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
31 
32 import java.lang.annotation.Retention;
33 import java.lang.annotation.RetentionPolicy;
34 
35 /**
36  * Handles {@link OmtpEvents} when {@link Vvm3Protocol} is being used. This handler writes custom
37  * error codes into the voicemail status table so support on the dialer side is required.
38  *
39  * TODO(b/29577838) disable VVM3 by default so support on system dialer can be ensured.
40  */
41 public class Vvm3EventHandler {
42 
43     private static final String TAG = "Vvm3EventHandler";
44 
45     @Retention(RetentionPolicy.SOURCE)
46     @IntDef({VMS_DNS_FAILURE, VMG_DNS_FAILURE, SPG_DNS_FAILURE, VMS_NO_CELLULAR, VMG_NO_CELLULAR,
47             SPG_NO_CELLULAR, VMS_TIMEOUT, VMG_TIMEOUT, STATUS_SMS_TIMEOUT, SUBSCRIBER_BLOCKED,
48             UNKNOWN_USER, UNKNOWN_DEVICE, INVALID_PASSWORD, MAILBOX_NOT_INITIALIZED,
49             SERVICE_NOT_PROVISIONED, SERVICE_NOT_ACTIVATED, USER_BLOCKED, IMAP_GETQUOTA_ERROR,
50             IMAP_SELECT_ERROR, IMAP_ERROR, VMG_INTERNAL_ERROR, VMG_DB_ERROR,
51             VMG_COMMUNICATION_ERROR, SPG_URL_NOT_FOUND, VMG_UNKNOWN_ERROR, PIN_NOT_SET})
52     public @interface ErrorCode {
53 
54     }
55 
56     public static final int VMS_DNS_FAILURE = -9001;
57     public static final int VMG_DNS_FAILURE = -9002;
58     public static final int SPG_DNS_FAILURE = -9003;
59     public static final int VMS_NO_CELLULAR = -9004;
60     public static final int VMG_NO_CELLULAR = -9005;
61     public static final int SPG_NO_CELLULAR = -9006;
62     public static final int VMS_TIMEOUT = -9007;
63     public static final int VMG_TIMEOUT = -9008;
64     public static final int STATUS_SMS_TIMEOUT = -9009;
65 
66     public static final int SUBSCRIBER_BLOCKED = -9990;
67     public static final int UNKNOWN_USER = -9991;
68     public static final int UNKNOWN_DEVICE = -9992;
69     public static final int INVALID_PASSWORD = -9993;
70     public static final int MAILBOX_NOT_INITIALIZED = -9994;
71     public static final int SERVICE_NOT_PROVISIONED = -9995;
72     public static final int SERVICE_NOT_ACTIVATED = -9996;
73     public static final int USER_BLOCKED = -9998;
74     public static final int IMAP_GETQUOTA_ERROR = -9997;
75     public static final int IMAP_SELECT_ERROR = -9989;
76     public static final int IMAP_ERROR = -9999;
77 
78     public static final int VMG_INTERNAL_ERROR = -101;
79     public static final int VMG_DB_ERROR = -102;
80     public static final int VMG_COMMUNICATION_ERROR = -103;
81     public static final int SPG_URL_NOT_FOUND = -301;
82 
83     // Non VVM3 codes:
84     public static final int VMG_UNKNOWN_ERROR = -1;
85     public static final int PIN_NOT_SET = -100;
86     // STATUS SMS returned st=U and rc!=2. The user cannot be provisioned and must contact customer
87     // support.
88     public static final int SUBSCRIBER_UNKNOWN = -99;
89 
90 
handleEvent(Context context, OmtpVvmCarrierConfigHelper config, VoicemailStatus.Editor status, OmtpEvents event)91     public static void handleEvent(Context context, OmtpVvmCarrierConfigHelper config,
92         VoicemailStatus.Editor status, OmtpEvents event) {
93         boolean handled = false;
94         switch (event.getType()) {
95             case Type.CONFIGURATION:
96                 handled = handleConfigurationEvent(context, status, event);
97                 break;
98             case Type.DATA_CHANNEL:
99                 handled = handleDataChannelEvent(status, event);
100                 break;
101             case Type.NOTIFICATION_CHANNEL:
102                 handled = handleNotificationChannelEvent(status, event);
103                 break;
104             case Type.OTHER:
105                 handled = handleOtherEvent(status, event);
106                 break;
107             default:
108                 com.android.services.telephony.Log
109                         .wtf(TAG, "invalid event type " + event.getType() + " for " + event);
110         }
111         if (!handled) {
112             DefaultOmtpEventHandler.handleEvent(context, config, status, event);
113         }
114     }
115 
handleConfigurationEvent(Context context, VoicemailStatus.Editor status, OmtpEvents event)116     private static boolean handleConfigurationEvent(Context context, VoicemailStatus.Editor status,
117         OmtpEvents event) {
118         switch (event) {
119             case CONFIG_REQUEST_STATUS_SUCCESS:
120                 if (!isPinRandomized(context, status.getPhoneAccountHandle())) {
121                     return false;
122                 } else {
123                     postError(status, PIN_NOT_SET);
124                 }
125                 break;
126             case CONFIG_ACTIVATING_SUBSEQUENT:
127                 if (isPinRandomized(context, status.getPhoneAccountHandle())) {
128                     status.setConfigurationState(PIN_NOT_SET);
129                 } else {
130                     status.setConfigurationState(Status.CONFIGURATION_STATE_OK);
131                 }
132                 status
133                         .setNotificationChannelState(Status.NOTIFICATION_CHANNEL_STATE_OK)
134                         .setDataChannelState(Status.DATA_CHANNEL_STATE_OK).apply();
135                 break;
136             case CONFIG_DEFAULT_PIN_REPLACED:
137                 postError(status, PIN_NOT_SET);
138                 break;
139             case CONFIG_STATUS_SMS_TIME_OUT:
140                 postError(status, STATUS_SMS_TIMEOUT);
141                 break;
142             default:
143                 return false;
144         }
145         return true;
146     }
147 
handleDataChannelEvent(VoicemailStatus.Editor status, OmtpEvents event)148     private static boolean handleDataChannelEvent(VoicemailStatus.Editor status, OmtpEvents event) {
149         switch (event) {
150             case DATA_NO_CONNECTION:
151             case DATA_NO_CONNECTION_CELLULAR_REQUIRED:
152             case DATA_ALL_SOCKET_CONNECTION_FAILED:
153                 postError(status, VMS_NO_CELLULAR);
154                 break;
155             case DATA_SSL_INVALID_HOST_NAME:
156             case DATA_CANNOT_ESTABLISH_SSL_SESSION:
157             case DATA_IOE_ON_OPEN:
158                 postError(status, VMS_TIMEOUT);
159                 break;
160             case DATA_CANNOT_RESOLVE_HOST_ON_NETWORK:
161                 postError(status, VMS_DNS_FAILURE);
162                 break;
163             case DATA_BAD_IMAP_CREDENTIAL:
164                 postError(status, IMAP_ERROR);
165                 break;
166             case DATA_AUTH_UNKNOWN_USER:
167                 postError(status, UNKNOWN_USER);
168                 break;
169             case DATA_AUTH_UNKNOWN_DEVICE:
170                 postError(status, UNKNOWN_DEVICE);
171                 break;
172             case DATA_AUTH_INVALID_PASSWORD:
173                 postError(status, INVALID_PASSWORD);
174                 break;
175             case DATA_AUTH_MAILBOX_NOT_INITIALIZED:
176                 postError(status, MAILBOX_NOT_INITIALIZED);
177                 break;
178             case DATA_AUTH_SERVICE_NOT_PROVISIONED:
179                 postError(status, SERVICE_NOT_PROVISIONED);
180                 break;
181             case DATA_AUTH_SERVICE_NOT_ACTIVATED:
182                 postError(status, SERVICE_NOT_ACTIVATED);
183                 break;
184             case DATA_AUTH_USER_IS_BLOCKED:
185                 postError(status, USER_BLOCKED);
186                 break;
187             case DATA_REJECTED_SERVER_RESPONSE:
188             case DATA_INVALID_INITIAL_SERVER_RESPONSE:
189             case DATA_SSL_EXCEPTION:
190                 postError(status, IMAP_ERROR);
191                 break;
192             default:
193                 return false;
194         }
195         return true;
196     }
197 
handleNotificationChannelEvent(VoicemailStatus.Editor status, OmtpEvents event)198     private static boolean handleNotificationChannelEvent(VoicemailStatus.Editor status,
199         OmtpEvents event) {
200         return false;
201     }
202 
handleOtherEvent(VoicemailStatus.Editor status, OmtpEvents event)203     private static boolean handleOtherEvent(VoicemailStatus.Editor status,
204             OmtpEvents event) {
205         switch (event) {
206             case VVM3_NEW_USER_SETUP_FAILED:
207                 postError(status, MAILBOX_NOT_INITIALIZED);
208                 break;
209             case VVM3_VMG_DNS_FAILURE:
210                 postError(status, VMG_DNS_FAILURE);
211                 break;
212             case VVM3_SPG_DNS_FAILURE:
213                 postError(status, SPG_DNS_FAILURE);
214                 break;
215             case VVM3_VMG_CONNECTION_FAILED:
216                 postError(status, VMG_NO_CELLULAR);
217                 break;
218             case VVM3_SPG_CONNECTION_FAILED:
219                 postError(status, SPG_NO_CELLULAR);
220                 break;
221             case VVM3_VMG_TIMEOUT:
222                 postError(status, VMG_TIMEOUT);
223                 break;
224             case VVM3_SUBSCRIBER_PROVISIONED:
225                 postError(status, SERVICE_NOT_ACTIVATED);
226                 break;
227             case VVM3_SUBSCRIBER_BLOCKED:
228                 postError(status, SUBSCRIBER_BLOCKED);
229                 break;
230             case VVM3_SUBSCRIBER_UNKNOWN:
231                 postError(status, SUBSCRIBER_UNKNOWN);
232                 break;
233             default:
234                 return false;
235         }
236         return true;
237     }
238 
postError(VoicemailStatus.Editor editor, @ErrorCode int errorCode)239     private static void postError(VoicemailStatus.Editor editor, @ErrorCode int errorCode) {
240         switch (errorCode) {
241             case VMG_DNS_FAILURE:
242             case SPG_DNS_FAILURE:
243             case VMG_NO_CELLULAR:
244             case SPG_NO_CELLULAR:
245             case VMG_TIMEOUT:
246             case SUBSCRIBER_BLOCKED:
247             case UNKNOWN_USER:
248             case UNKNOWN_DEVICE:
249             case INVALID_PASSWORD:
250             case MAILBOX_NOT_INITIALIZED:
251             case SERVICE_NOT_PROVISIONED:
252             case SERVICE_NOT_ACTIVATED:
253             case USER_BLOCKED:
254             case VMG_UNKNOWN_ERROR:
255             case SPG_URL_NOT_FOUND:
256             case VMG_INTERNAL_ERROR:
257             case VMG_DB_ERROR:
258             case VMG_COMMUNICATION_ERROR:
259             case PIN_NOT_SET:
260             case SUBSCRIBER_UNKNOWN:
261                 editor.setConfigurationState(errorCode);
262                 break;
263             case VMS_NO_CELLULAR:
264             case VMS_DNS_FAILURE:
265             case VMS_TIMEOUT:
266             case IMAP_GETQUOTA_ERROR:
267             case IMAP_SELECT_ERROR:
268             case IMAP_ERROR:
269                 editor.setDataChannelState(errorCode);
270                 break;
271             case STATUS_SMS_TIMEOUT:
272                 editor.setNotificationChannelState(errorCode);
273                 break;
274             default:
275                 Log.wtf(TAG, "unknown error code: " + errorCode);
276         }
277         editor.apply();
278     }
279 
isPinRandomized(Context context, PhoneAccountHandle phoneAccountHandle)280     private static boolean isPinRandomized(Context context, PhoneAccountHandle phoneAccountHandle) {
281         if (phoneAccountHandle == null) {
282             // This should never happen.
283             Log.e(TAG, "status editor has null phone account handle");
284             return false;
285         }
286         return VoicemailChangePinActivity.isDefaultOldPinSet(context, phoneAccountHandle);
287     }
288 }
289