summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/voicemail/listui/error/OmtpVoicemailMessageCreator.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/android/dialer/voicemail/listui/error/OmtpVoicemailMessageCreator.java')
-rw-r--r--java/com/android/dialer/voicemail/listui/error/OmtpVoicemailMessageCreator.java322
1 files changed, 322 insertions, 0 deletions
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<Action> 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);
+ }
+}