diff options
Diffstat (limited to 'java/com/android/voicemailomtp/protocol')
8 files changed, 0 insertions, 1184 deletions
diff --git a/java/com/android/voicemailomtp/protocol/CvvmProtocol.java b/java/com/android/voicemailomtp/protocol/CvvmProtocol.java deleted file mode 100644 index 48ed99709..000000000 --- a/java/com/android/voicemailomtp/protocol/CvvmProtocol.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.voicemailomtp.protocol; - -import android.content.Context; -import android.telecom.PhoneAccountHandle; -import android.telephony.SmsManager; - -import com.android.voicemailomtp.OmtpConstants; -import com.android.voicemailomtp.sms.OmtpCvvmMessageSender; -import com.android.voicemailomtp.sms.OmtpMessageSender; - -/** - * A flavor of OMTP protocol with a different mobile originated (MO) format - * - * Used by carriers such as T-Mobile - */ -public class CvvmProtocol extends VisualVoicemailProtocol { - - private static String IMAP_CHANGE_TUI_PWD_FORMAT = "CHANGE_TUI_PWD PWD=%1$s OLD_PWD=%2$s"; - private static String IMAP_CHANGE_VM_LANG_FORMAT = "CHANGE_VM_LANG Lang=%1$s"; - private static String IMAP_CLOSE_NUT = "CLOSE_NUT"; - - @Override - public OmtpMessageSender createMessageSender(Context context, - PhoneAccountHandle phoneAccountHandle, short applicationPort, - String destinationNumber) { - return new OmtpCvvmMessageSender(context, phoneAccountHandle, applicationPort, - destinationNumber); - } - - @Override - public String getCommand(String command) { - if (command == OmtpConstants.IMAP_CHANGE_TUI_PWD_FORMAT) { - return IMAP_CHANGE_TUI_PWD_FORMAT; - } - if (command == OmtpConstants.IMAP_CLOSE_NUT) { - return IMAP_CLOSE_NUT; - } - if (command == OmtpConstants.IMAP_CHANGE_VM_LANG_FORMAT) { - return IMAP_CHANGE_VM_LANG_FORMAT; - } - return super.getCommand(command); - } -} diff --git a/java/com/android/voicemailomtp/protocol/OmtpProtocol.java b/java/com/android/voicemailomtp/protocol/OmtpProtocol.java deleted file mode 100644 index d88a23285..000000000 --- a/java/com/android/voicemailomtp/protocol/OmtpProtocol.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.voicemailomtp.protocol; - -import android.content.Context; -import android.telecom.PhoneAccountHandle; -import android.telephony.SmsManager; - -import com.android.voicemailomtp.OmtpConstants; -import com.android.voicemailomtp.sms.OmtpMessageSender; -import com.android.voicemailomtp.sms.OmtpStandardMessageSender; - -public class OmtpProtocol extends VisualVoicemailProtocol { - - @Override - public OmtpMessageSender createMessageSender(Context context, - PhoneAccountHandle phoneAccountHandle, short applicationPort, - String destinationNumber) { - return new OmtpStandardMessageSender(context, phoneAccountHandle, applicationPort, - destinationNumber, - null, OmtpConstants.PROTOCOL_VERSION1_1, null); - } -} diff --git a/java/com/android/voicemailomtp/protocol/ProtocolHelper.java b/java/com/android/voicemailomtp/protocol/ProtocolHelper.java deleted file mode 100644 index 4fca199bf..000000000 --- a/java/com/android/voicemailomtp/protocol/ProtocolHelper.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.voicemailomtp.protocol; - -import android.telephony.SmsManager; -import android.text.TextUtils; - -import com.android.voicemailomtp.OmtpVvmCarrierConfigHelper; -import com.android.voicemailomtp.VvmLog; -import com.android.voicemailomtp.sms.OmtpMessageSender; - -public class ProtocolHelper { - - private static final String TAG = "ProtocolHelper"; - - public static OmtpMessageSender getMessageSender(VisualVoicemailProtocol protocol, - OmtpVvmCarrierConfigHelper config) { - - int applicationPort = config.getApplicationPort(); - String destinationNumber = config.getDestinationNumber(); - if (TextUtils.isEmpty(destinationNumber)) { - VvmLog.w(TAG, "No destination number for this carrier."); - return null; - } - - return protocol.createMessageSender(config.getContext(), config.getPhoneAccountHandle(), - (short) applicationPort, destinationNumber); - } -} diff --git a/java/com/android/voicemailomtp/protocol/VisualVoicemailProtocol.java b/java/com/android/voicemailomtp/protocol/VisualVoicemailProtocol.java deleted file mode 100644 index 9ff2ed167..000000000 --- a/java/com/android/voicemailomtp/protocol/VisualVoicemailProtocol.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.voicemailomtp.protocol; - -import android.app.PendingIntent; -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.Nullable; -import android.telecom.PhoneAccountHandle; -import android.telephony.SmsManager; -import com.android.voicemailomtp.ActivationTask; -import com.android.voicemailomtp.DefaultOmtpEventHandler; -import com.android.voicemailomtp.OmtpEvents; -import com.android.voicemailomtp.OmtpVvmCarrierConfigHelper; -import com.android.voicemailomtp.VoicemailStatus; -import com.android.voicemailomtp.sms.OmtpMessageSender; -import com.android.voicemailomtp.sms.StatusMessage; - -public abstract class VisualVoicemailProtocol { - - /** - * Activation should cause the carrier to respond with a STATUS SMS. - */ - public void startActivation(OmtpVvmCarrierConfigHelper config, PendingIntent sentIntent) { - OmtpMessageSender messageSender = ProtocolHelper.getMessageSender(this, config); - if (messageSender != null) { - messageSender.requestVvmActivation(sentIntent); - } - } - - public void startDeactivation(OmtpVvmCarrierConfigHelper config) { - OmtpMessageSender messageSender = ProtocolHelper.getMessageSender(this, config); - if (messageSender != null) { - messageSender.requestVvmDeactivation(null); - } - } - - public boolean supportsProvisioning() { - return false; - } - - public void startProvisioning(ActivationTask task, PhoneAccountHandle handle, - OmtpVvmCarrierConfigHelper config, VoicemailStatus.Editor editor, StatusMessage message, - Bundle data) { - // Do nothing - } - - public void requestStatus(OmtpVvmCarrierConfigHelper config, - @Nullable PendingIntent sentIntent) { - OmtpMessageSender messageSender = ProtocolHelper.getMessageSender(this, config); - if (messageSender != null) { - messageSender.requestVvmStatus(sentIntent); - } - } - - public abstract OmtpMessageSender createMessageSender(Context context, - PhoneAccountHandle phoneAccountHandle, - short applicationPort, String destinationNumber); - - /** - * Translate an OMTP IMAP command to the protocol specific one. For example, changing the TUI - * password on OMTP is XCHANGE_TUI_PWD, but on CVVM and VVM3 it is CHANGE_TUI_PWD. - * - * @param command A String command in {@link com.android.voicemailomtp.OmtpConstants}, the exact - * instance should be used instead of its' value. - * @returns Translated command, or {@code null} if not available in this protocol - */ - public String getCommand(String command) { - return command; - } - - public void handleEvent(Context context, OmtpVvmCarrierConfigHelper config, - VoicemailStatus.Editor status, OmtpEvents event) { - DefaultOmtpEventHandler.handleEvent(context, config, status, event); - } - - /** - * Given an VVM SMS with an unknown {@code event}, let the protocol attempt to translate it into - * an equivalent STATUS SMS. Returns {@code null} if it cannot be translated. - */ - @Nullable - public Bundle translateStatusSmsBundle(OmtpVvmCarrierConfigHelper config, String event, - Bundle data) { - return null; - } -} diff --git a/java/com/android/voicemailomtp/protocol/VisualVoicemailProtocolFactory.java b/java/com/android/voicemailomtp/protocol/VisualVoicemailProtocolFactory.java deleted file mode 100644 index b74f503c6..000000000 --- a/java/com/android/voicemailomtp/protocol/VisualVoicemailProtocolFactory.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.voicemailomtp.protocol; - -import android.content.res.Resources; -import android.support.annotation.Nullable; -import android.telephony.TelephonyManager; -import com.android.voicemailomtp.VvmLog; - -public class VisualVoicemailProtocolFactory { - - private static final String TAG = "VvmProtocolFactory"; - - private static final String VVM_TYPE_VVM3 = "vvm_type_vvm3"; - - @Nullable - public static VisualVoicemailProtocol create(Resources resources, String type) { - if (type == null) { - return null; - } - switch (type) { - case TelephonyManager.VVM_TYPE_OMTP: - return new OmtpProtocol(); - case TelephonyManager.VVM_TYPE_CVVM: - return new CvvmProtocol(); - case VVM_TYPE_VVM3: - return new Vvm3Protocol(); - default: - VvmLog.e(TAG, "Unexpected visual voicemail type: " + type); - } - return null; - } -} diff --git a/java/com/android/voicemailomtp/protocol/Vvm3EventHandler.java b/java/com/android/voicemailomtp/protocol/Vvm3EventHandler.java deleted file mode 100644 index 72646386c..000000000 --- a/java/com/android/voicemailomtp/protocol/Vvm3EventHandler.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.voicemailomtp.protocol; - -import android.content.Context; -import android.support.annotation.IntDef; -import android.util.Log; -import com.android.voicemailomtp.DefaultOmtpEventHandler; -import com.android.voicemailomtp.OmtpEvents; -import com.android.voicemailomtp.OmtpEvents.Type; -import com.android.voicemailomtp.OmtpVvmCarrierConfigHelper; -import com.android.voicemailomtp.VoicemailStatus; -import com.android.voicemailomtp.settings.VoicemailChangePinActivity; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Handles {@link OmtpEvents} when {@link Vvm3Protocol} is being used. This handler writes custom - * error codes into the voicemail status table so support on the dialer side is required. - * - * TODO(b/29577838) disable VVM3 by default so support on system dialer can be ensured. - */ -public class Vvm3EventHandler { - - private static final String TAG = "Vvm3EventHandler"; - - @Retention(RetentionPolicy.SOURCE) - @IntDef({VMS_DNS_FAILURE, VMG_DNS_FAILURE, SPG_DNS_FAILURE, VMS_NO_CELLULAR, VMG_NO_CELLULAR, - SPG_NO_CELLULAR, VMS_TIMEOUT, VMG_TIMEOUT, STATUS_SMS_TIMEOUT, SUBSCRIBER_BLOCKED, - UNKNOWN_USER, UNKNOWN_DEVICE, INVALID_PASSWORD, MAILBOX_NOT_INITIALIZED, - SERVICE_NOT_PROVISIONED, SERVICE_NOT_ACTIVATED, USER_BLOCKED, IMAP_GETQUOTA_ERROR, - IMAP_SELECT_ERROR, IMAP_ERROR, VMG_INTERNAL_ERROR, VMG_DB_ERROR, - VMG_COMMUNICATION_ERROR, SPG_URL_NOT_FOUND, VMG_UNKNOWN_ERROR, PIN_NOT_SET}) - public @interface ErrorCode { - - } - - public static final int VMS_DNS_FAILURE = -9001; - public static final int VMG_DNS_FAILURE = -9002; - public static final int SPG_DNS_FAILURE = -9003; - public static final int VMS_NO_CELLULAR = -9004; - public static final int VMG_NO_CELLULAR = -9005; - public static final int SPG_NO_CELLULAR = -9006; - public static final int VMS_TIMEOUT = -9007; - public static final int VMG_TIMEOUT = -9008; - public static final int STATUS_SMS_TIMEOUT = -9009; - - public static final int SUBSCRIBER_BLOCKED = -9990; - public static final int UNKNOWN_USER = -9991; - public static final int UNKNOWN_DEVICE = -9992; - public static final int INVALID_PASSWORD = -9993; - public static final int MAILBOX_NOT_INITIALIZED = -9994; - public static final int SERVICE_NOT_PROVISIONED = -9995; - public static final int SERVICE_NOT_ACTIVATED = -9996; - public static final int USER_BLOCKED = -9998; - public static final int IMAP_GETQUOTA_ERROR = -9997; - public static final int IMAP_SELECT_ERROR = -9989; - public static final int IMAP_ERROR = -9999; - - public static final int VMG_INTERNAL_ERROR = -101; - public static final int VMG_DB_ERROR = -102; - public static final int VMG_COMMUNICATION_ERROR = -103; - public static final int SPG_URL_NOT_FOUND = -301; - - // Non VVM3 codes: - public static final int VMG_UNKNOWN_ERROR = -1; - public static final int PIN_NOT_SET = -100; - // STATUS SMS returned st=U and rc!=2. The user cannot be provisioned and must contact customer - // support. - public static final int SUBSCRIBER_UNKNOWN = -99; - - - public static void handleEvent(Context context, OmtpVvmCarrierConfigHelper config, - VoicemailStatus.Editor status, OmtpEvents event) { - boolean handled = false; - switch (event.getType()) { - case Type.CONFIGURATION: - handled = handleConfigurationEvent(context, status, event); - break; - case Type.DATA_CHANNEL: - handled = handleDataChannelEvent(status, event); - break; - case Type.NOTIFICATION_CHANNEL: - handled = handleNotificationChannelEvent(status, event); - break; - case Type.OTHER: - handled = handleOtherEvent(status, event); - break; - default: - Log.wtf(TAG, "invalid event type " + event.getType() + " for " + event); - } - if (!handled) { - DefaultOmtpEventHandler.handleEvent(context, config, status, event); - } - } - - private static boolean handleConfigurationEvent(Context context, VoicemailStatus.Editor status, - OmtpEvents event) { - switch (event) { - case CONFIG_REQUEST_STATUS_SUCCESS: - if (status.getPhoneAccountHandle() == null) { - // This should never happen. - Log.e(TAG, "status editor has null phone account handle"); - return true; - } - - if (!VoicemailChangePinActivity - .isDefaultOldPinSet(context, status.getPhoneAccountHandle())) { - return false; - } else { - postError(status, PIN_NOT_SET); - } - break; - case CONFIG_DEFAULT_PIN_REPLACED: - postError(status, PIN_NOT_SET); - break; - case CONFIG_STATUS_SMS_TIME_OUT: - postError(status, STATUS_SMS_TIMEOUT); - break; - default: - return false; - } - return true; - } - - private static boolean handleDataChannelEvent(VoicemailStatus.Editor status, OmtpEvents event) { - switch (event) { - case DATA_NO_CONNECTION: - case DATA_NO_CONNECTION_CELLULAR_REQUIRED: - case DATA_ALL_SOCKET_CONNECTION_FAILED: - postError(status, VMS_NO_CELLULAR); - break; - case DATA_SSL_INVALID_HOST_NAME: - case DATA_CANNOT_ESTABLISH_SSL_SESSION: - case DATA_IOE_ON_OPEN: - postError(status, VMS_TIMEOUT); - break; - case DATA_CANNOT_RESOLVE_HOST_ON_NETWORK: - postError(status, VMS_DNS_FAILURE); - break; - case DATA_BAD_IMAP_CREDENTIAL: - postError(status, IMAP_ERROR); - break; - case DATA_AUTH_UNKNOWN_USER: - postError(status, UNKNOWN_USER); - break; - case DATA_AUTH_UNKNOWN_DEVICE: - postError(status, UNKNOWN_DEVICE); - break; - case DATA_AUTH_INVALID_PASSWORD: - postError(status, INVALID_PASSWORD); - break; - case DATA_AUTH_MAILBOX_NOT_INITIALIZED: - postError(status, MAILBOX_NOT_INITIALIZED); - break; - case DATA_AUTH_SERVICE_NOT_PROVISIONED: - postError(status, SERVICE_NOT_PROVISIONED); - break; - case DATA_AUTH_SERVICE_NOT_ACTIVATED: - postError(status, SERVICE_NOT_ACTIVATED); - break; - case DATA_AUTH_USER_IS_BLOCKED: - postError(status, USER_BLOCKED); - break; - case DATA_REJECTED_SERVER_RESPONSE: - case DATA_INVALID_INITIAL_SERVER_RESPONSE: - case DATA_SSL_EXCEPTION: - postError(status, IMAP_ERROR); - break; - default: - return false; - } - return true; - } - - private static boolean handleNotificationChannelEvent(VoicemailStatus.Editor status, - OmtpEvents event) { - return false; - } - - private static boolean handleOtherEvent(VoicemailStatus.Editor status, - OmtpEvents event) { - switch (event) { - case VVM3_NEW_USER_SETUP_FAILED: - postError(status, MAILBOX_NOT_INITIALIZED); - break; - case VVM3_VMG_DNS_FAILURE: - postError(status, VMG_DNS_FAILURE); - break; - case VVM3_SPG_DNS_FAILURE: - postError(status, SPG_DNS_FAILURE); - break; - case VVM3_VMG_CONNECTION_FAILED: - postError(status, VMG_NO_CELLULAR); - break; - case VVM3_SPG_CONNECTION_FAILED: - postError(status, SPG_NO_CELLULAR); - break; - case VVM3_VMG_TIMEOUT: - postError(status, VMG_TIMEOUT); - break; - case VVM3_SUBSCRIBER_PROVISIONED: - postError(status, SERVICE_NOT_ACTIVATED); - break; - case VVM3_SUBSCRIBER_BLOCKED: - postError(status, SUBSCRIBER_BLOCKED); - break; - case VVM3_SUBSCRIBER_UNKNOWN: - postError(status, SUBSCRIBER_UNKNOWN); - break; - default: - return false; - } - return true; - } - - private static void postError(VoicemailStatus.Editor editor, @ErrorCode int errorCode) { - switch (errorCode) { - case VMG_DNS_FAILURE: - case SPG_DNS_FAILURE: - case VMG_NO_CELLULAR: - case SPG_NO_CELLULAR: - case VMG_TIMEOUT: - case SUBSCRIBER_BLOCKED: - case UNKNOWN_USER: - case UNKNOWN_DEVICE: - case INVALID_PASSWORD: - case MAILBOX_NOT_INITIALIZED: - case SERVICE_NOT_PROVISIONED: - case SERVICE_NOT_ACTIVATED: - case USER_BLOCKED: - case VMG_UNKNOWN_ERROR: - case SPG_URL_NOT_FOUND: - case VMG_INTERNAL_ERROR: - case VMG_DB_ERROR: - case VMG_COMMUNICATION_ERROR: - case PIN_NOT_SET: - case SUBSCRIBER_UNKNOWN: - editor.setConfigurationState(errorCode); - break; - case VMS_NO_CELLULAR: - case VMS_DNS_FAILURE: - case VMS_TIMEOUT: - case IMAP_GETQUOTA_ERROR: - case IMAP_SELECT_ERROR: - case IMAP_ERROR: - editor.setDataChannelState(errorCode); - break; - case STATUS_SMS_TIMEOUT: - editor.setNotificationChannelState(errorCode); - break; - default: - Log.wtf(TAG, "unknown error code: " + errorCode); - } - editor.apply(); - } -} diff --git a/java/com/android/voicemailomtp/protocol/Vvm3Protocol.java b/java/com/android/voicemailomtp/protocol/Vvm3Protocol.java deleted file mode 100644 index 652d1010a..000000000 --- a/java/com/android/voicemailomtp/protocol/Vvm3Protocol.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.voicemailomtp.protocol; - -import android.annotation.TargetApi; -import android.app.PendingIntent; -import android.content.Context; -import android.net.Network; -import android.os.Build.VERSION_CODES; -import android.os.Bundle; -import android.support.annotation.Nullable; -import android.telecom.PhoneAccountHandle; -import android.text.TextUtils; -import com.android.voicemailomtp.ActivationTask; -import com.android.voicemailomtp.OmtpConstants; -import com.android.voicemailomtp.OmtpEvents; -import com.android.voicemailomtp.OmtpVvmCarrierConfigHelper; -import com.android.voicemailomtp.VisualVoicemailPreferences; -import com.android.voicemailomtp.VoicemailStatus; -import com.android.voicemailomtp.VvmLog; -import com.android.voicemailomtp.imap.ImapHelper; -import com.android.voicemailomtp.imap.ImapHelper.InitializingException; -import com.android.voicemailomtp.mail.MessagingException; -import com.android.voicemailomtp.settings.VisualVoicemailSettingsUtil; -import com.android.voicemailomtp.settings.VoicemailChangePinActivity; -import com.android.voicemailomtp.sms.OmtpMessageSender; -import com.android.voicemailomtp.sms.StatusMessage; -import com.android.voicemailomtp.sms.Vvm3MessageSender; -import com.android.voicemailomtp.sync.VvmNetworkRequest; -import com.android.voicemailomtp.sync.VvmNetworkRequest.NetworkWrapper; -import com.android.voicemailomtp.sync.VvmNetworkRequest.RequestFailedException; -import java.io.IOException; -import java.security.SecureRandom; -import java.util.Locale; - -/** - * A flavor of OMTP protocol with a different provisioning process - * - * <p>Used by carriers such as Verizon Wireless - */ -@TargetApi(VERSION_CODES.CUR_DEVELOPMENT) -public class Vvm3Protocol extends VisualVoicemailProtocol { - - private static final String TAG = "Vvm3Protocol"; - - private static final String SMS_EVENT_UNRECOGNIZED = "UNRECOGNIZED"; - private static final String SMS_EVENT_UNRECOGNIZED_CMD = "cmd"; - private static final String SMS_EVENT_UNRECOGNIZED_STATUS = "STATUS"; - private static final String DEFAULT_VMG_URL_KEY = "default_vmg_url"; - - private static final String IMAP_CHANGE_TUI_PWD_FORMAT = "CHANGE_TUI_PWD PWD=%1$s OLD_PWD=%2$s"; - private static final String IMAP_CHANGE_VM_LANG_FORMAT = "CHANGE_VM_LANG Lang=%1$s"; - private static final String IMAP_CLOSE_NUT = "CLOSE_NUT"; - - private static final String ISO639_Spanish = "es"; - - /** - * For VVM3, if the STATUS SMS returns {@link StatusMessage#getProvisioningStatus()} of {@link - * OmtpConstants#SUBSCRIBER_UNKNOWN} and {@link StatusMessage#getReturnCode()} of this value, - * the user can self-provision visual voicemail service. For other response codes, the user must - * contact customer support to resolve the issue. - */ - private static final String VVM3_UNKNOWN_SUBSCRIBER_CAN_SUBSCRIBE_RESPONSE_CODE = "2"; - - // Default prompt level when using the telephone user interface. - // Standard prompt when the user call into the voicemail, and no prompts when someone else is - // leaving a voicemail. - private static final String VVM3_VM_LANGUAGE_ENGLISH_STANDARD_NO_GUEST_PROMPTS = "5"; - private static final String VVM3_VM_LANGUAGE_SPANISH_STANDARD_NO_GUEST_PROMPTS = "6"; - - private static final int DEFAULT_PIN_LENGTH = 6; - - @Override - public void startActivation(OmtpVvmCarrierConfigHelper config, - @Nullable PendingIntent sentIntent) { - // VVM3 does not support activation SMS. - // Send a status request which will start the provisioning process if the user is not - // provisioned. - VvmLog.i(TAG, "Activating"); - config.requestStatus(sentIntent); - } - - @Override - public void startDeactivation(OmtpVvmCarrierConfigHelper config) { - // VVM3 does not support deactivation. - // do nothing. - } - - @Override - public boolean supportsProvisioning() { - return true; - } - - @Override - public void startProvisioning(ActivationTask task, PhoneAccountHandle phoneAccountHandle, - OmtpVvmCarrierConfigHelper config, VoicemailStatus.Editor status, StatusMessage message, - Bundle data) { - VvmLog.i(TAG, "start vvm3 provisioning"); - if (OmtpConstants.SUBSCRIBER_UNKNOWN.equals(message.getProvisioningStatus())) { - VvmLog.i(TAG, "Provisioning status: Unknown"); - if (VVM3_UNKNOWN_SUBSCRIBER_CAN_SUBSCRIBE_RESPONSE_CODE - .equals(message.getReturnCode())) { - VvmLog.i(TAG, "Self provisioning available, subscribing"); - new Vvm3Subscriber(task, phoneAccountHandle, config, status, data).subscribe(); - } else { - config.handleEvent(status, OmtpEvents.VVM3_SUBSCRIBER_UNKNOWN); - } - } else if (OmtpConstants.SUBSCRIBER_NEW.equals(message.getProvisioningStatus())) { - VvmLog.i(TAG, "setting up new user"); - // Save the IMAP credentials in preferences so they are persistent and can be retrieved. - VisualVoicemailPreferences prefs = - new VisualVoicemailPreferences(config.getContext(), phoneAccountHandle); - message.putStatus(prefs.edit()).apply(); - - startProvisionNewUser(task, phoneAccountHandle, config, status, message); - } else if (OmtpConstants.SUBSCRIBER_PROVISIONED.equals(message.getProvisioningStatus())) { - VvmLog.i(TAG, "User provisioned but not activated, disabling VVM"); - VisualVoicemailSettingsUtil - .setEnabled(config.getContext(), phoneAccountHandle, false); - } else if (OmtpConstants.SUBSCRIBER_BLOCKED.equals(message.getProvisioningStatus())) { - VvmLog.i(TAG, "User blocked"); - config.handleEvent(status, OmtpEvents.VVM3_SUBSCRIBER_BLOCKED); - } - } - - @Override - public OmtpMessageSender createMessageSender(Context context, - PhoneAccountHandle phoneAccountHandle, short applicationPort, - String destinationNumber) { - return new Vvm3MessageSender(context, phoneAccountHandle, applicationPort, - destinationNumber); - } - - @Override - public void handleEvent(Context context, OmtpVvmCarrierConfigHelper config, - VoicemailStatus.Editor status, OmtpEvents event) { - Vvm3EventHandler.handleEvent(context, config, status, event); - } - - @Override - public String getCommand(String command) { - if (command == OmtpConstants.IMAP_CHANGE_TUI_PWD_FORMAT) { - return IMAP_CHANGE_TUI_PWD_FORMAT; - } - if (command == OmtpConstants.IMAP_CLOSE_NUT) { - return IMAP_CLOSE_NUT; - } - if (command == OmtpConstants.IMAP_CHANGE_VM_LANG_FORMAT) { - return IMAP_CHANGE_VM_LANG_FORMAT; - } - return super.getCommand(command); - } - - @Override - public Bundle translateStatusSmsBundle(OmtpVvmCarrierConfigHelper config, String event, - Bundle data) { - // UNRECOGNIZED?cmd=STATUS is the response of a STATUS request when the user is provisioned - // with iPhone visual voicemail without VoLTE. Translate it into an unprovisioned status - // so provisioning can be done. - if (!SMS_EVENT_UNRECOGNIZED.equals(event)) { - return null; - } - if (!SMS_EVENT_UNRECOGNIZED_STATUS.equals(data.getString(SMS_EVENT_UNRECOGNIZED_CMD))) { - return null; - } - Bundle bundle = new Bundle(); - bundle.putString(OmtpConstants.PROVISIONING_STATUS, OmtpConstants.SUBSCRIBER_UNKNOWN); - bundle.putString(OmtpConstants.RETURN_CODE, - VVM3_UNKNOWN_SUBSCRIBER_CAN_SUBSCRIBE_RESPONSE_CODE); - String vmgUrl = config.getString(DEFAULT_VMG_URL_KEY); - if (TextUtils.isEmpty(vmgUrl)) { - VvmLog.e(TAG, "Unable to translate STATUS SMS: VMG URL is not set in config"); - return null; - } - bundle.putString(Vvm3Subscriber.VMG_URL_KEY, vmgUrl); - VvmLog.i(TAG, "UNRECOGNIZED?cmd=STATUS translated into unprovisioned STATUS SMS"); - return bundle; - } - - private void startProvisionNewUser(ActivationTask task, PhoneAccountHandle phoneAccountHandle, - OmtpVvmCarrierConfigHelper config, VoicemailStatus.Editor status, - StatusMessage message) { - try (NetworkWrapper wrapper = VvmNetworkRequest - .getNetwork(config, phoneAccountHandle, status)) { - Network network = wrapper.get(); - - VvmLog.i(TAG, "new user: network available"); - try (ImapHelper helper = new ImapHelper(config.getContext(), phoneAccountHandle, - network, status)) { - // VVM3 has inconsistent error language code to OMTP. Just issue a raw command - // here. - // TODO(b/29082671): use LocaleList - if (Locale.getDefault().getLanguage() - .equals(new Locale(ISO639_Spanish).getLanguage())) { - // Spanish - helper.changeVoicemailTuiLanguage( - VVM3_VM_LANGUAGE_SPANISH_STANDARD_NO_GUEST_PROMPTS); - } else { - // English - helper.changeVoicemailTuiLanguage( - VVM3_VM_LANGUAGE_ENGLISH_STANDARD_NO_GUEST_PROMPTS); - } - VvmLog.i(TAG, "new user: language set"); - - if (setPin(config.getContext(), phoneAccountHandle, helper, message)) { - // Only close new user tutorial if the PIN has been changed. - helper.closeNewUserTutorial(); - VvmLog.i(TAG, "new user: NUT closed"); - - config.requestStatus(null); - } - } catch (InitializingException | MessagingException | IOException e) { - config.handleEvent(status, OmtpEvents.VVM3_NEW_USER_SETUP_FAILED); - task.fail(); - VvmLog.e(TAG, e.toString()); - } - } catch (RequestFailedException e) { - config.handleEvent(status, OmtpEvents.DATA_NO_CONNECTION_CELLULAR_REQUIRED); - task.fail(); - } - - } - - - private static boolean setPin(Context context, PhoneAccountHandle phoneAccountHandle, - ImapHelper helper, StatusMessage message) - throws IOException, MessagingException { - String defaultPin = getDefaultPin(message); - if (defaultPin == null) { - VvmLog.i(TAG, "cannot generate default PIN"); - return false; - } - - if (VoicemailChangePinActivity.isDefaultOldPinSet(context, phoneAccountHandle)) { - // The pin was already set - VvmLog.i(TAG, "PIN already set"); - return true; - } - String newPin = generatePin(getMinimumPinLength(context, phoneAccountHandle)); - if (helper.changePin(defaultPin, newPin) == OmtpConstants.CHANGE_PIN_SUCCESS) { - VoicemailChangePinActivity.setDefaultOldPIN(context, phoneAccountHandle, newPin); - helper.handleEvent(OmtpEvents.CONFIG_DEFAULT_PIN_REPLACED); - } - VvmLog.i(TAG, "new user: PIN set"); - return true; - } - - @Nullable - private static String getDefaultPin(StatusMessage message) { - // The IMAP username is [phone number]@example.com - String username = message.getImapUserName(); - try { - String number = username.substring(0, username.indexOf('@')); - if (number.length() < 4) { - VvmLog.e(TAG, "unable to extract number from IMAP username"); - return null; - } - return "1" + number.substring(number.length() - 4); - } catch (StringIndexOutOfBoundsException e) { - VvmLog.e(TAG, "unable to extract number from IMAP username"); - return null; - } - - } - - private static int getMinimumPinLength(Context context, PhoneAccountHandle phoneAccountHandle) { - VisualVoicemailPreferences preferences = new VisualVoicemailPreferences(context, - phoneAccountHandle); - // The OMTP pin length format is {min}-{max} - String[] lengths = preferences.getString(OmtpConstants.TUI_PASSWORD_LENGTH, "").split("-"); - if (lengths.length == 2) { - try { - return Integer.parseInt(lengths[0]); - } catch (NumberFormatException e) { - return DEFAULT_PIN_LENGTH; - } - } - return DEFAULT_PIN_LENGTH; - } - - private static String generatePin(int length) { - SecureRandom random = new SecureRandom(); - return String.format(Locale.US, "%010d", Math.abs(random.nextLong())) - .substring(0, length); - - } -} diff --git a/java/com/android/voicemailomtp/protocol/Vvm3Subscriber.java b/java/com/android/voicemailomtp/protocol/Vvm3Subscriber.java deleted file mode 100644 index 0a4d792b2..000000000 --- a/java/com/android/voicemailomtp/protocol/Vvm3Subscriber.java +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.voicemailomtp.protocol; - -import android.annotation.TargetApi; -import android.net.Network; -import android.os.Build; -import android.os.Build.VERSION_CODES; -import android.os.Bundle; -import android.support.annotation.WorkerThread; -import android.telecom.PhoneAccountHandle; -import android.telephony.TelephonyManager; -import android.text.Html; -import android.text.Spanned; -import android.text.style.URLSpan; -import android.util.ArrayMap; -import com.android.voicemailomtp.ActivationTask; -import com.android.voicemailomtp.Assert; -import com.android.voicemailomtp.OmtpEvents; -import com.android.voicemailomtp.OmtpVvmCarrierConfigHelper; -import com.android.voicemailomtp.VoicemailStatus; -import com.android.voicemailomtp.VvmLog; -import com.android.voicemailomtp.sync.VvmNetworkRequest; -import com.android.voicemailomtp.sync.VvmNetworkRequest.NetworkWrapper; -import com.android.voicemailomtp.sync.VvmNetworkRequest.RequestFailedException; -import com.android.volley.AuthFailureError; -import com.android.volley.Request; -import com.android.volley.RequestQueue; -import com.android.volley.toolbox.HurlStack; -import com.android.volley.toolbox.RequestFuture; -import com.android.volley.toolbox.StringRequest; -import com.android.volley.toolbox.Volley; -import java.io.IOException; -import java.net.CookieHandler; -import java.net.CookieManager; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.Locale; -import java.util.Map; -import java.util.Random; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Class to subscribe to basic VVM3 visual voicemail, for example, Verizon. Subscription is required - * when the user is unprovisioned. This could happen when the user is on a legacy service, or - * switched over from devices that used other type of visual voicemail. - * - * <p>The STATUS SMS will come with a URL to the voicemail management gateway. From it we can find - * the self provisioning gateway URL that we can modify voicemail services. - * - * <p>A request to the self provisioning gateway to activate basic visual voicemail will return us - * with a web page. If the user hasn't subscribe to it yet it will contain a link to confirm the - * subscription. This link should be clicked through cellular network, and have cookies enabled. - * - * <p>After the process is completed, the carrier should send us another STATUS SMS with a new or - * ready user. - */ -@TargetApi(VERSION_CODES.CUR_DEVELOPMENT) -public class Vvm3Subscriber { - - private static final String TAG = "Vvm3Subscriber"; - - private static final String OPERATION_GET_SPG_URL = "retrieveSPGURL"; - private static final String SPG_URL_TAG = "spgurl"; - private static final String TRANSACTION_ID_TAG = "transactionid"; - //language=XML - private static final String VMG_XML_REQUEST_FORMAT = "" - + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - + "<VMGVVMRequest>" - + " <MessageHeader>" - + " <transactionid>%1$s</transactionid>" - + " </MessageHeader>" - + " <MessageBody>" - + " <mdn>%2$s</mdn>" - + " <operation>%3$s</operation>" - + " <source>Device</source>" - + " <devicemodel>%4$s</devicemodel>" - + " </MessageBody>" - + "</VMGVVMRequest>"; - - static final String VMG_URL_KEY = "vmg_url"; - - // Self provisioning POST key/values. VVM3 API 2.1.0 12.3 - private static final String SPG_VZW_MDN_PARAM = "VZW_MDN"; - private static final String SPG_VZW_SERVICE_PARAM = "VZW_SERVICE"; - private static final String SPG_VZW_SERVICE_BASIC = "BVVM"; - private static final String SPG_DEVICE_MODEL_PARAM = "DEVICE_MODEL"; - // Value for all android device - private static final String SPG_DEVICE_MODEL_ANDROID = "DROID_4G"; - private static final String SPG_APP_TOKEN_PARAM = "APP_TOKEN"; - private static final String SPG_APP_TOKEN = "q8e3t5u2o1"; - private static final String SPG_LANGUAGE_PARAM = "SPG_LANGUAGE_PARAM"; - private static final String SPG_LANGUAGE_EN = "ENGLISH"; - - private static final String BASIC_SUBSCRIBE_LINK_TEXT = "Subscribe to Basic Visual Voice Mail"; - - private static final int REQUEST_TIMEOUT_SECONDS = 30; - - private final ActivationTask mTask; - private final PhoneAccountHandle mHandle; - private final OmtpVvmCarrierConfigHelper mHelper; - private final VoicemailStatus.Editor mStatus; - private final Bundle mData; - - private final String mNumber; - - private RequestQueue mRequestQueue; - - private static class ProvisioningException extends Exception { - - public ProvisioningException(String message) { - super(message); - } - } - - static { - // Set the default cookie handler to retain session data for the self provisioning gateway. - // Note; this is not ideal as it is application-wide, and can easily get clobbered. - // But it seems to be the preferred way to manage cookie for HttpURLConnection, and manually - // managing cookies will greatly increase complexity. - CookieManager cookieManager = new CookieManager(); - CookieHandler.setDefault(cookieManager); - } - - @WorkerThread - public Vvm3Subscriber(ActivationTask task, PhoneAccountHandle handle, - OmtpVvmCarrierConfigHelper helper, VoicemailStatus.Editor status, Bundle data) { - Assert.isNotMainThread(); - mTask = task; - mHandle = handle; - mHelper = helper; - mStatus = status; - mData = data; - - // Assuming getLine1Number() will work with VVM3. For unprovisioned users the IMAP username - // is not included in the status SMS, thus no other way to get the current phone number. - mNumber = mHelper.getContext().getSystemService(TelephonyManager.class) - .createForPhoneAccountHandle(mHandle).getLine1Number(); - } - - @WorkerThread - public void subscribe() { - Assert.isNotMainThread(); - // Cellular data is required to subscribe. - // processSubscription() is called after network is available. - VvmLog.i(TAG, "Subscribing"); - - try (NetworkWrapper wrapper = VvmNetworkRequest.getNetwork(mHelper, mHandle, mStatus)) { - Network network = wrapper.get(); - VvmLog.d(TAG, "provisioning: network available"); - mRequestQueue = Volley - .newRequestQueue(mHelper.getContext(), new NetworkSpecifiedHurlStack(network)); - processSubscription(); - } catch (RequestFailedException e) { - mHelper.handleEvent(mStatus, OmtpEvents.VVM3_VMG_CONNECTION_FAILED); - mTask.fail(); - } - } - - private void processSubscription() { - try { - String gatewayUrl = getSelfProvisioningGateway(); - String selfProvisionResponse = getSelfProvisionResponse(gatewayUrl); - String subscribeLink = findSubscribeLink(selfProvisionResponse); - clickSubscribeLink(subscribeLink); - } catch (ProvisioningException e) { - VvmLog.e(TAG, e.toString()); - mTask.fail(); - } - } - - /** - * Get the URL to perform self-provisioning from the voicemail management gateway. - */ - private String getSelfProvisioningGateway() throws ProvisioningException { - VvmLog.i(TAG, "retrieving SPG URL"); - String response = vvm3XmlRequest(OPERATION_GET_SPG_URL); - return extractText(response, SPG_URL_TAG); - } - - /** - * Sent a request to the self-provisioning gateway, which will return us with a webpage. The - * page might contain a "Subscribe to Basic Visual Voice Mail" link to complete the - * subscription. The cookie from this response and cellular data is required to click the link. - */ - private String getSelfProvisionResponse(String url) throws ProvisioningException { - VvmLog.i(TAG, "Retrieving self provisioning response"); - - RequestFuture<String> future = RequestFuture.newFuture(); - - StringRequest stringRequest = new StringRequest(Request.Method.POST, url, future, future) { - @Override - protected Map<String, String> getParams() { - Map<String, String> params = new ArrayMap<>(); - params.put(SPG_VZW_MDN_PARAM, mNumber); - params.put(SPG_VZW_SERVICE_PARAM, SPG_VZW_SERVICE_BASIC); - params.put(SPG_DEVICE_MODEL_PARAM, SPG_DEVICE_MODEL_ANDROID); - params.put(SPG_APP_TOKEN_PARAM, SPG_APP_TOKEN); - // Language to display the subscription page. The page is never shown to the user - // so just use English. - params.put(SPG_LANGUAGE_PARAM, SPG_LANGUAGE_EN); - return params; - } - }; - - mRequestQueue.add(stringRequest); - try { - return future.get(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS); - } catch (InterruptedException | ExecutionException | TimeoutException e) { - mHelper.handleEvent(mStatus, OmtpEvents.VVM3_SPG_CONNECTION_FAILED); - throw new ProvisioningException(e.toString()); - } - } - - private void clickSubscribeLink(String subscribeLink) throws ProvisioningException { - VvmLog.i(TAG, "Clicking subscribe link"); - RequestFuture<String> future = RequestFuture.newFuture(); - - StringRequest stringRequest = new StringRequest(Request.Method.POST, - subscribeLink, future, future); - mRequestQueue.add(stringRequest); - try { - // A new STATUS SMS will be sent after this request. - future.get(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS); - } catch (TimeoutException | ExecutionException | InterruptedException e) { - mHelper.handleEvent(mStatus, OmtpEvents.VVM3_SPG_CONNECTION_FAILED); - throw new ProvisioningException(e.toString()); - } - // It could take very long for the STATUS SMS to return. Waiting for it is unreliable. - // Just leave the CONFIG STATUS as CONFIGURING and end the task. The user can always - // manually retry if it took too long. - } - - private String vvm3XmlRequest(String operation) throws ProvisioningException { - VvmLog.d(TAG, "Sending vvm3XmlRequest for " + operation); - String voicemailManagementGateway = mData.getString(VMG_URL_KEY); - if (voicemailManagementGateway == null) { - VvmLog.e(TAG, "voicemailManagementGateway url unknown"); - return null; - } - String transactionId = createTransactionId(); - String body = String.format(Locale.US, VMG_XML_REQUEST_FORMAT, - transactionId, mNumber, operation, Build.MODEL); - - RequestFuture<String> future = RequestFuture.newFuture(); - StringRequest stringRequest = new StringRequest(Request.Method.POST, - voicemailManagementGateway, future, future) { - @Override - public byte[] getBody() throws AuthFailureError { - return body.getBytes(); - } - }; - mRequestQueue.add(stringRequest); - - try { - String response = future.get(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS); - if (!transactionId.equals(extractText(response, TRANSACTION_ID_TAG))) { - throw new ProvisioningException("transactionId mismatch"); - } - return response; - } catch (InterruptedException | ExecutionException | TimeoutException e) { - mHelper.handleEvent(mStatus, OmtpEvents.VVM3_VMG_CONNECTION_FAILED); - throw new ProvisioningException(e.toString()); - } - } - - private String findSubscribeLink(String response) throws ProvisioningException { - Spanned doc = Html.fromHtml(response, Html.FROM_HTML_MODE_LEGACY); - URLSpan[] spans = doc.getSpans(0, doc.length(), URLSpan.class); - StringBuilder fulltext = new StringBuilder(); - for (URLSpan span : spans) { - String text = doc.subSequence(doc.getSpanStart(span), doc.getSpanEnd(span)).toString(); - if (BASIC_SUBSCRIBE_LINK_TEXT.equals(text)) { - return span.getURL(); - } - fulltext.append(text); - } - throw new ProvisioningException("Subscribe link not found: " + fulltext); - } - - private String createTransactionId() { - return String.valueOf(Math.abs(new Random().nextLong())); - } - - private String extractText(String xml, String tag) throws ProvisioningException { - Pattern pattern = Pattern.compile("<" + tag + ">(.*)<\\/" + tag + ">"); - Matcher matcher = pattern.matcher(xml); - if (matcher.find()) { - return matcher.group(1); - } - throw new ProvisioningException("Tag " + tag + " not found in xml response"); - } - - private static class NetworkSpecifiedHurlStack extends HurlStack { - - private final Network mNetwork; - - public NetworkSpecifiedHurlStack(Network network) { - mNetwork = network; - } - - @Override - protected HttpURLConnection createConnection(URL url) throws IOException { - return (HttpURLConnection) mNetwork.openConnection(url); - } - - } -} |