From 4deaebc5a988eb83440693721f1ab28b180d8779 Mon Sep 17 00:00:00 2001 From: uabdullah Date: Mon, 22 Jan 2018 18:19:07 -0800 Subject: Move legacy voicemail/error to nui voicemail/listui/error All packages relating to NUI voicemail should be under third_party/java_src/android_app/dialer/java/com/android/dialer/voicemail/listui. Since there is a chance that during NUI development the legacy third_party/java_src/android_app/dialer/java/com/android/dialer/app/voicemail/error might undergo changes, it makes sense to move this package to the nui, so that no changes in the legacy code are missed for nui. This refactoring would also allow us to ensure that the strings do not need to be translated and that most of the code can be re-used for nui by hooking up the fragment and adapter to voicemail/listui/error. Bug: 71700117 Test: Unit tests PiperOrigin-RevId: 182868896 Change-Id: I23329654df5ce2bf612101708ed001ca308ae1ac --- .../listui/error/OmtpVoicemailMessageCreator.java | 322 +++++++++++++++++++++ 1 file changed, 322 insertions(+) create mode 100644 java/com/android/dialer/voicemail/listui/error/OmtpVoicemailMessageCreator.java (limited to 'java/com/android/dialer/voicemail/listui/error/OmtpVoicemailMessageCreator.java') diff --git a/java/com/android/dialer/voicemail/listui/error/OmtpVoicemailMessageCreator.java b/java/com/android/dialer/voicemail/listui/error/OmtpVoicemailMessageCreator.java new file mode 100644 index 000000000..29b698942 --- /dev/null +++ b/java/com/android/dialer/voicemail/listui/error/OmtpVoicemailMessageCreator.java @@ -0,0 +1,322 @@ +/* + * 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.dialer.voicemail.listui.error; + +import android.content.Context; +import android.preference.PreferenceManager; +import android.provider.VoicemailContract.Status; +import android.support.annotation.Nullable; +import android.telecom.PhoneAccountHandle; +import com.android.dialer.common.LogUtil; +import com.android.dialer.common.PerAccountSharedPreferences; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.Logger; +import com.android.dialer.voicemail.listui.error.VoicemailErrorMessage.Action; +import com.android.voicemail.VoicemailClient; +import com.android.voicemail.VoicemailComponent; +import java.util.ArrayList; +import java.util.List; + +/** + * Create error message from {@link VoicemailStatus} for OMTP visual voicemail. This is also the + * default behavior if other message creator does not handle the status. + */ +public class OmtpVoicemailMessageCreator { + + private static final float QUOTA_NEAR_FULL_THRESHOLD = 0.9f; + private static final float QUOTA_FULL_THRESHOLD = 0.99f; + protected static final String VOICEMAIL_PROMO_DISMISSED_KEY = + "voicemail_archive_promo_was_dismissed"; + protected static final String VOICEMAIL_PROMO_ALMOST_FULL_DISMISSED_KEY = + "voicemail_archive_almost_full_promo_was_dismissed"; + + @Nullable + public static VoicemailErrorMessage create( + Context context, VoicemailStatus status, final VoicemailStatusReader statusReader) { + VoicemailErrorMessage tosMessage = + new VoicemailTosMessageCreator(context, status, statusReader).maybeCreateTosMessage(); + if (tosMessage != null) { + return tosMessage; + } + + if (Status.CONFIGURATION_STATE_OK == status.configurationState + && Status.DATA_CHANNEL_STATE_OK == status.dataChannelState + && Status.NOTIFICATION_CHANNEL_STATE_OK == status.notificationChannelState) { + return checkQuota(context, status, statusReader); + } + // Initial state when the source is activating. Other error might be written into data and + // notification channel during activation. + if (Status.CONFIGURATION_STATE_CONFIGURING == status.configurationState + && Status.DATA_CHANNEL_STATE_OK == status.dataChannelState + && Status.NOTIFICATION_CHANNEL_STATE_OK == status.notificationChannelState) { + return new VoicemailErrorMessage( + context.getString(R.string.voicemail_error_activating_title), + context.getString(R.string.voicemail_error_activating_message), + VoicemailErrorMessage.createCallVoicemailAction(context, status.getPhoneAccountHandle())); + } + + if (Status.NOTIFICATION_CHANNEL_STATE_NO_CONNECTION == status.notificationChannelState) { + return createNoSignalMessage(context, status); + } + + if (Status.CONFIGURATION_STATE_FAILED == status.configurationState) { + return new VoicemailErrorMessage( + context.getString(R.string.voicemail_error_activation_failed_title), + context.getString(R.string.voicemail_error_activation_failed_message), + VoicemailErrorMessage.createCallVoicemailAction(context, status.getPhoneAccountHandle()), + VoicemailErrorMessage.createRetryAction(context, status)); + } + + if (Status.DATA_CHANNEL_STATE_NO_CONNECTION == status.dataChannelState) { + return new VoicemailErrorMessage( + context.getString(R.string.voicemail_error_no_data_title), + context.getString(R.string.voicemail_error_no_data_message), + VoicemailErrorMessage.createCallVoicemailAction(context, status.getPhoneAccountHandle()), + VoicemailErrorMessage.createRetryAction(context, status)); + } + + if (Status.DATA_CHANNEL_STATE_NO_CONNECTION_CELLULAR_REQUIRED == status.dataChannelState) { + return new VoicemailErrorMessage( + context.getString(R.string.voicemail_error_no_data_title), + context.getString(R.string.voicemail_error_no_data_cellular_required_message), + VoicemailErrorMessage.createCallVoicemailAction(context, status.getPhoneAccountHandle()), + VoicemailErrorMessage.createRetryAction(context, status)); + } + + if (Status.DATA_CHANNEL_STATE_BAD_CONFIGURATION == status.dataChannelState) { + return new VoicemailErrorMessage( + context.getString(R.string.voicemail_error_bad_config_title), + context.getString(R.string.voicemail_error_bad_config_message), + VoicemailErrorMessage.createCallVoicemailAction(context, status.getPhoneAccountHandle()), + VoicemailErrorMessage.createRetryAction(context, status)); + } + + if (Status.DATA_CHANNEL_STATE_COMMUNICATION_ERROR == status.dataChannelState) { + return new VoicemailErrorMessage( + context.getString(R.string.voicemail_error_communication_title), + context.getString(R.string.voicemail_error_communication_message), + VoicemailErrorMessage.createCallVoicemailAction(context, status.getPhoneAccountHandle()), + VoicemailErrorMessage.createRetryAction(context, status)); + } + + if (Status.DATA_CHANNEL_STATE_SERVER_ERROR == status.dataChannelState) { + return new VoicemailErrorMessage( + context.getString(R.string.voicemail_error_server_title), + context.getString(R.string.voicemail_error_server_message), + VoicemailErrorMessage.createCallVoicemailAction(context, status.getPhoneAccountHandle()), + VoicemailErrorMessage.createRetryAction(context, status)); + } + + if (Status.DATA_CHANNEL_STATE_SERVER_CONNECTION_ERROR == status.dataChannelState) { + return new VoicemailErrorMessage( + context.getString(R.string.voicemail_error_server_connection_title), + context.getString(R.string.voicemail_error_server_connection_message), + VoicemailErrorMessage.createCallVoicemailAction(context, status.getPhoneAccountHandle()), + VoicemailErrorMessage.createRetryAction(context, status)); + } + + // This should be an assertion error, but there's a bug in NYC-DR (a bug) that will + // sometimes give status mixed from multiple SIMs. There's no meaningful message to be displayed + // from it, so just suppress the message. + LogUtil.e("OmtpVoicemailMessageCreator.create", "Unhandled status: " + status); + return null; + } + + public static boolean isSyncBlockingError(VoicemailStatus status) { + if (status.notificationChannelState != Status.NOTIFICATION_CHANNEL_STATE_OK) { + return true; + } + + if (status.dataChannelState != Status.DATA_CHANNEL_STATE_OK) { + return true; + } + + switch (status.configurationState) { + case Status.CONFIGURATION_STATE_OK: + // allow activation to be queued again in case it is interrupted + case Status.CONFIGURATION_STATE_CONFIGURING: + return false; + default: + return true; + } + } + + @Nullable + private static VoicemailErrorMessage checkQuota( + Context context, VoicemailStatus status, VoicemailStatusReader statusReader) { + if (status.quotaOccupied != Status.QUOTA_UNAVAILABLE + && status.quotaTotal != Status.QUOTA_UNAVAILABLE) { + return createInboxErrorMessage(context, status, statusReader); + } + Logger.get(context).logImpression(DialerImpression.Type.VVM_QUOTA_CHECK_UNAVAILABLE); + return null; + } + + @Nullable + private static VoicemailErrorMessage createInboxErrorMessage( + Context context, VoicemailStatus status, VoicemailStatusReader statusReader) { + + float voicemailOccupiedFraction = (float) status.quotaOccupied / (float) status.quotaTotal; + + if (voicemailOccupiedFraction < QUOTA_NEAR_FULL_THRESHOLD) { + return null; + } + + boolean isFull = voicemailOccupiedFraction >= QUOTA_FULL_THRESHOLD; + + PhoneAccountHandle phoneAccountHandle = status.getPhoneAccountHandle(); + + PerAccountSharedPreferences sharedPreferenceForAccount = + new PerAccountSharedPreferences( + context, phoneAccountHandle, PreferenceManager.getDefaultSharedPreferences(context)); + + VoicemailClient voicemailClient = VoicemailComponent.get(context).getVoicemailClient(); + + boolean shouldShowPromoForArchive = + !isPromoForArchiveDismissed(sharedPreferenceForAccount, isFull) + && !voicemailClient.isVoicemailArchiveEnabled(context, phoneAccountHandle) + && voicemailClient.isVoicemailArchiveAvailable(context); + + if (!shouldShowPromoForArchive) { + if (isFull) { + Logger.get(context) + .logImpression(DialerImpression.Type.VVM_USER_SHOWN_VM_FULL_ERROR_MESSAGE); + return new VoicemailErrorMessage( + context.getString(R.string.voicemail_error_inbox_full_title), + context.getString(R.string.voicemail_error_inbox_full_message)); + } else { + Logger.get(context) + .logImpression(DialerImpression.Type.VVM_USER_SHOWN_VM_ALMOST_FULL_ERROR_MESSAGE); + return new VoicemailErrorMessage( + context.getString(R.string.voicemail_error_inbox_near_full_title), + context.getString(R.string.voicemail_error_inbox_near_full_message)); + } + } + + String title; + CharSequence message; + DialerImpression.Type enabledImpression; + DialerImpression.Type dismissedImpression; + String dismissedKey; + + if (isFull) { + Logger.get(context).logImpression(DialerImpression.Type.VVM_USER_SHOWN_VM_FULL_PROMO); + title = context.getString(R.string.voicemail_error_inbox_full_turn_archive_on_title); + message = context.getText(R.string.voicemail_error_inbox_full_turn_archive_on_message); + enabledImpression = DialerImpression.Type.VVM_USER_ENABLED_ARCHIVE_FROM_VM_FULL_PROMO; + dismissedImpression = DialerImpression.Type.VVM_USER_DISMISSED_VM_FULL_PROMO; + dismissedKey = VOICEMAIL_PROMO_DISMISSED_KEY; + } else { + Logger.get(context).logImpression(DialerImpression.Type.VVM_USER_SHOWN_VM_ALMOST_FULL_PROMO); + title = context.getString(R.string.voicemail_error_inbox_almost_full_turn_archive_on_title); + message = context.getText(R.string.voicemail_error_inbox_almost_full_turn_archive_on_message); + enabledImpression = DialerImpression.Type.VVM_USER_ENABLED_ARCHIVE_FROM_VM_ALMOST_FULL_PROMO; + dismissedImpression = DialerImpression.Type.VVM_USER_DISMISSED_VM_ALMOST_FULL_PROMO; + dismissedKey = VOICEMAIL_PROMO_ALMOST_FULL_DISMISSED_KEY; + } + + return createVMQuotaPromo( + context, + phoneAccountHandle, + status, + statusReader, + voicemailClient, + sharedPreferenceForAccount, + title, + message, + enabledImpression, + dismissedImpression, + dismissedKey); + } + + private static boolean isPromoForArchiveDismissed( + PerAccountSharedPreferences sharedPreferenceForAccount, boolean isFull) { + if (isFull) { + return sharedPreferenceForAccount.getBoolean(VOICEMAIL_PROMO_DISMISSED_KEY, false); + } else { + return sharedPreferenceForAccount.getBoolean( + VOICEMAIL_PROMO_ALMOST_FULL_DISMISSED_KEY, false); + } + } + + private static VoicemailErrorMessage createVMQuotaPromo( + Context context, + PhoneAccountHandle phoneAccountHandle, + VoicemailStatus status, + VoicemailStatusReader statusReader, + VoicemailClient voicemailClient, + PerAccountSharedPreferences sharedPreferenceForAccount, + String title, + CharSequence message, + DialerImpression.Type impressionToLogOnEnable, + DialerImpression.Type impressionToLogOnDismiss, + String preferenceKeyToUpdate) { + return new VoicemailErrorMessage( + title, + message, + VoicemailErrorMessage.createTurnArchiveOnAction( + context, + impressionToLogOnEnable, + status, + statusReader, + voicemailClient, + phoneAccountHandle), + VoicemailErrorMessage.createDismissTurnArchiveOnAction( + context, + impressionToLogOnDismiss, + statusReader, + sharedPreferenceForAccount, + preferenceKeyToUpdate)); + } + + @Nullable + private static VoicemailErrorMessage createNoSignalMessage( + Context context, VoicemailStatus status) { + CharSequence title; + CharSequence description; + List actions = new ArrayList<>(); + if (Status.CONFIGURATION_STATE_OK == status.configurationState) { + if (Status.DATA_CHANNEL_STATE_NO_CONNECTION_CELLULAR_REQUIRED == status.dataChannelState) { + title = context.getString(R.string.voicemail_error_no_signal_title); + description = + context.getString(R.string.voicemail_error_no_signal_cellular_required_message); + } else { + title = context.getString(R.string.voicemail_error_no_signal_title); + if (status.isAirplaneMode) { + description = context.getString(R.string.voicemail_error_no_signal_airplane_mode_message); + } else { + description = context.getString(R.string.voicemail_error_no_signal_message); + } + actions.add(VoicemailErrorMessage.createSyncAction(context, status)); + } + } else { + title = context.getString(R.string.voicemail_error_not_activate_no_signal_title); + if (status.isAirplaneMode) { + description = + context.getString( + R.string.voicemail_error_not_activate_no_signal_airplane_mode_message); + } else { + description = context.getString(R.string.voicemail_error_not_activate_no_signal_message); + actions.add(VoicemailErrorMessage.createRetryAction(context, status)); + } + } + if (status.isAirplaneMode) { + actions.add(VoicemailErrorMessage.createChangeAirplaneModeAction(context)); + } + return new VoicemailErrorMessage(title, description, actions); + } +} -- cgit v1.2.3