1 /* 2 * Copyright (C) 2017 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.dialer.app.voicemail.error; 18 19 import android.app.AlertDialog; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.content.DialogInterface; 23 import android.content.Intent; 24 import android.content.SharedPreferences; 25 import android.graphics.Typeface; 26 import android.preference.PreferenceManager; 27 import android.support.annotation.Nullable; 28 import android.telecom.PhoneAccountHandle; 29 import android.telephony.TelephonyManager; 30 import android.text.SpannableString; 31 import android.text.style.StyleSpan; 32 import android.view.View; 33 import android.view.View.OnClickListener; 34 import com.android.contacts.common.compat.TelephonyManagerCompat; 35 import com.android.dialer.app.voicemail.error.VoicemailErrorMessage.Action; 36 import com.android.dialer.common.LogUtil; 37 import com.android.dialer.configprovider.ConfigProviderBindings; 38 import com.android.dialer.logging.DialerImpression; 39 import com.android.dialer.logging.Logger; 40 import com.android.voicemail.VisualVoicemailTypeExtensions; 41 import com.android.voicemail.VoicemailClient; 42 import com.android.voicemail.VoicemailComponent; 43 import java.util.Locale; 44 45 /** 46 * Create error message from {@link VoicemailStatus} for voicemail. This is will show different 47 * terms of service for Verizon and for other carriers. 48 */ 49 public class VoicemailTosMessageCreator { 50 // Flag to check which version of the Verizon ToS that the user has accepted. 51 public static final String VVM3_TOS_VERSION_ACCEPTED_KEY = "vvm3_tos_version_accepted"; 52 53 // Flag to check which version of the Google Dialer ToS that the user has accepted. 54 public static final String DIALER_TOS_VERSION_ACCEPTED_KEY = "dialer_tos_version_accepted"; 55 56 public static final int CURRENT_VVM3_TOS_VERSION = 2; 57 public static final int CURRENT_DIALER_TOS_VERSION = 1; 58 59 private static final String ISO639_SPANISH = "es"; 60 61 private final Context context; 62 private final VoicemailStatus status; 63 private final VoicemailStatusReader statusReader; 64 private final SharedPreferences preferences; 65 66 VoicemailTosMessageCreator( 67 final Context context, 68 final VoicemailStatus status, 69 final VoicemailStatusReader statusReader) { 70 this.context = context; 71 this.status = status; 72 this.statusReader = statusReader; 73 this.preferences = PreferenceManager.getDefaultSharedPreferences(context); 74 } 75 76 @Nullable 77 VoicemailErrorMessage maybeCreateTosMessage() { 78 // TODO: add filtering based on carrier 79 if (hasAcceptedTos()) { 80 return null; 81 } 82 83 if (!shouldShowTos()) { 84 return null; 85 } 86 87 logTosCreatedImpression(); 88 89 return new VoicemailTosMessage( 90 getTosTitle(), 91 getTosMessage(), 92 new Action( 93 getDeclineText(), 94 new OnClickListener() { 95 @Override 96 public void onClick(View v) { 97 LogUtil.i("VoicemailTosMessageCreator.maybeShowTosMessage", "decline clicked"); 98 PhoneAccountHandle handle = 99 new PhoneAccountHandle( 100 ComponentName.unflattenFromString(status.phoneAccountComponentName), 101 status.phoneAccountId); 102 logTosDeclinedImpression(); 103 showDeclineTosDialog(handle); 104 } 105 }), 106 new Action( 107 getAcceptText(), 108 new OnClickListener() { 109 @Override 110 public void onClick(View v) { 111 LogUtil.i("VoicemailTosMessageCreator.maybeShowTosMessage", "accept clicked"); 112 recordTosAcceptance(); 113 logTosAcceptedImpression(); 114 statusReader.refresh(); 115 } 116 }, 117 true /* raised */)) 118 .setModal(true) 119 .setImageResourceId(getTosImageId()); 120 } 121 122 private boolean shouldShowTos() { 123 if (isVvm3()) { 124 LogUtil.i("VoicemailTosMessageCreator.shouldShowTos", "showing TOS for verizon"); 125 return true; 126 } 127 128 if (isVoicemailTranscriptionEnabled()) { 129 LogUtil.i( 130 "VoicemailTosMessageCreator.shouldShowTos", "showing TOS for Google transcription users"); 131 return true; 132 } 133 134 return false; 135 } 136 137 private boolean isVoicemailTranscriptionEnabled() { 138 return ConfigProviderBindings.get(context).getBoolean("voicemail_transcription_enabled", false); 139 } 140 141 private void showDeclineTosDialog(final PhoneAccountHandle handle) { 142 if (isVvm3() && Vvm3VoicemailMessageCreator.PIN_NOT_SET == status.configurationState) { 143 LogUtil.i( 144 "VoicemailTosMessageCreator.showDeclineTosDialog", "PIN_NOT_SET, showing set PIN dialog"); 145 showSetPinBeforeDeclineDialog(); 146 return; 147 } 148 LogUtil.i( 149 "VoicemailTosMessageCreator.showDeclineVerizonTosDialog", 150 "showing decline ToS dialog, status=" + status); 151 final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 152 AlertDialog.Builder builder = new AlertDialog.Builder(context); 153 builder.setMessage(getTosDeclinedDialogMessageId()); 154 builder.setPositiveButton( 155 getTosDeclinedDialogDowngradeId(), 156 new DialogInterface.OnClickListener() { 157 @Override 158 public void onClick(DialogInterface dialog, int which) { 159 Logger.get(context).logImpression(DialerImpression.Type.VOICEMAIL_VVM3_TOS_DECLINED); 160 VoicemailClient voicemailClient = VoicemailComponent.get(context).getVoicemailClient(); 161 if (voicemailClient.isVoicemailModuleEnabled()) { 162 voicemailClient.setVoicemailEnabled(context, status.getPhoneAccountHandle(), false); 163 } else { 164 TelephonyManagerCompat.setVisualVoicemailEnabled(telephonyManager, handle, false); 165 } 166 } 167 }); 168 169 builder.setNegativeButton( 170 android.R.string.cancel, 171 new DialogInterface.OnClickListener() { 172 @Override 173 public void onClick(DialogInterface dialog, int which) { 174 dialog.dismiss(); 175 } 176 }); 177 178 builder.setCancelable(true); 179 builder.show(); 180 } 181 182 private void showSetPinBeforeDeclineDialog() { 183 AlertDialog.Builder builder = new AlertDialog.Builder(context); 184 builder.setMessage(R.string.verizon_terms_and_conditions_decline_set_pin_dialog_message); 185 builder.setPositiveButton( 186 R.string.verizon_terms_and_conditions_decline_set_pin_dialog_set_pin, 187 new DialogInterface.OnClickListener() { 188 @Override 189 public void onClick(DialogInterface dialog, int which) { 190 Logger.get(context) 191 .logImpression(DialerImpression.Type.VOICEMAIL_VVM3_TOS_DECLINE_CHANGE_PIN_SHOWN); 192 Intent intent = new Intent(TelephonyManager.ACTION_CONFIGURE_VOICEMAIL); 193 context.startActivity(intent); 194 } 195 }); 196 197 builder.setNegativeButton( 198 android.R.string.cancel, 199 new DialogInterface.OnClickListener() { 200 @Override 201 public void onClick(DialogInterface dialog, int which) { 202 dialog.dismiss(); 203 } 204 }); 205 206 builder.setCancelable(true); 207 builder.show(); 208 } 209 210 private boolean isVvm3() { 211 return VisualVoicemailTypeExtensions.VVM_TYPE_VVM3.equals(status.type); 212 } 213 214 private boolean useSpanish() { 215 return Locale.getDefault().getLanguage().equals(new Locale(ISO639_SPANISH).getLanguage()); 216 } 217 218 private boolean hasAcceptedTos() { 219 if (isVvm3()) { 220 return preferences.getInt(VVM3_TOS_VERSION_ACCEPTED_KEY, 0) >= CURRENT_VVM3_TOS_VERSION; 221 } else { 222 return preferences.getInt(DIALER_TOS_VERSION_ACCEPTED_KEY, 0) >= CURRENT_DIALER_TOS_VERSION; 223 } 224 } 225 226 private void recordTosAcceptance() { 227 if (isVvm3()) { 228 preferences.edit().putInt(VVM3_TOS_VERSION_ACCEPTED_KEY, CURRENT_VVM3_TOS_VERSION).apply(); 229 } else { 230 preferences 231 .edit() 232 .putInt(DIALER_TOS_VERSION_ACCEPTED_KEY, CURRENT_DIALER_TOS_VERSION) 233 .apply(); 234 } 235 } 236 237 private void logTosCreatedImpression() { 238 if (isVvm3()) { 239 Logger.get(context).logImpression(DialerImpression.Type.VOICEMAIL_VVM3_TOS_V2_CREATED); 240 } else { 241 Logger.get(context).logImpression(DialerImpression.Type.VOICEMAIL_DIALER_TOS_CREATED); 242 } 243 } 244 245 private void logTosDeclinedImpression() { 246 if (isVvm3()) { 247 Logger.get(context) 248 .logImpression(DialerImpression.Type.VOICEMAIL_VVM3_TOS_V2_DECLINE_CLICKED); 249 } else { 250 Logger.get(context).logImpression(DialerImpression.Type.VOICEMAIL_DIALER_TOS_DECLINE_CLICKED); 251 } 252 } 253 254 private void logTosAcceptedImpression() { 255 if (isVvm3()) { 256 Logger.get(context).logImpression(DialerImpression.Type.VOICEMAIL_VVM3_TOS_V2_ACCEPTED); 257 } else { 258 Logger.get(context).logImpression(DialerImpression.Type.VOICEMAIL_DIALER_TOS_ACCEPTED); 259 } 260 } 261 262 private CharSequence getVvm3Tos() { 263 return useSpanish() 264 ? context.getString(R.string.verizon_terms_and_conditions_1_1_spanish) 265 : context.getString(R.string.verizon_terms_and_conditions_1_1_english); 266 } 267 268 private CharSequence getDialerTos() { 269 if (!isVoicemailTranscriptionEnabled()) { 270 return ""; 271 } 272 273 return useSpanish() 274 ? context.getString(R.string.dialer_terms_and_conditions_1_0_spanish) 275 : context.getString(R.string.dialer_terms_and_conditions_1_0_english); 276 } 277 278 private CharSequence getAcceptText() { 279 if (isVvm3()) { 280 return useSpanish() 281 ? context.getString(R.string.verizon_terms_and_conditions_accept_spanish) 282 : context.getString(R.string.verizon_terms_and_conditions_accept_english); 283 } else { 284 return useSpanish() 285 ? context.getString(R.string.dialer_terms_and_conditions_accept_spanish) 286 : context.getString(R.string.dialer_terms_and_conditions_accept_english); 287 } 288 } 289 290 private CharSequence getDeclineText() { 291 if (isVvm3()) { 292 return useSpanish() 293 ? context.getString(R.string.verizon_terms_and_conditions_decline_spanish) 294 : context.getString(R.string.verizon_terms_and_conditions_decline_english); 295 } else { 296 return useSpanish() 297 ? context.getString(R.string.dialer_terms_and_conditions_decline_spanish) 298 : context.getString(R.string.dialer_terms_and_conditions_decline_english); 299 } 300 } 301 302 private CharSequence getTosTitle() { 303 return isVvm3() 304 ? context.getString(R.string.verizon_terms_and_conditions_title) 305 : context.getString(R.string.dialer_terms_and_conditions_title); 306 } 307 308 private CharSequence getTosMessage() { 309 if (isVvm3()) { 310 // For verizon the TOS consist of three pieces: google dialer TOS, Verizon TOS message and 311 // Verizon TOS details. 312 CharSequence vvm3Details = getVvm3Tos(); 313 CharSequence tos = 314 context.getString( 315 R.string.verizon_terms_and_conditions_message, getDialerTos(), vvm3Details); 316 // Make all text bold except the details. 317 SpannableString spannableTos = new SpannableString(tos); 318 spannableTos.setSpan(new StyleSpan(Typeface.BOLD), 0, tos.length() - vvm3Details.length(), 0); 319 return spannableTos; 320 } else { 321 // The TOS for everyone else there are no details, so just make everything bold. 322 CharSequence tos = 323 context.getString(R.string.dialer_terms_and_conditions_message, getDialerTos()); 324 SpannableString spannableTos = new SpannableString(tos); 325 spannableTos.setSpan(new StyleSpan(Typeface.BOLD), 0, tos.length(), 0); 326 return spannableTos; 327 } 328 } 329 330 private int getTosDeclinedDialogMessageId() { 331 return isVvm3() 332 ? R.string.verizon_terms_and_conditions_decline_dialog_message 333 : R.string.dialer_terms_and_conditions_decline_dialog_message; 334 } 335 336 private int getTosDeclinedDialogDowngradeId() { 337 return isVvm3() 338 ? R.string.verizon_terms_and_conditions_decline_dialog_downgrade 339 : R.string.dialer_terms_and_conditions_decline_dialog_downgrade; 340 } 341 342 private Integer getTosImageId() { 343 return isVvm3() ? null : R.drawable.voicemail_tos_image; 344 } 345 } 346