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