1 /** 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * <p>http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * <p>Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 * express or implied. See the License for the specific language governing permissions and 12 * limitations under the License 13 */ 14 package com.android.dialer.voicemail.settings; 15 16 import android.annotation.TargetApi; 17 import android.app.AlertDialog; 18 import android.content.DialogInterface; 19 import android.content.Intent; 20 import android.os.Build.VERSION_CODES; 21 import android.os.Bundle; 22 import android.preference.Preference; 23 import android.preference.Preference.OnPreferenceClickListener; 24 import android.preference.PreferenceFragment; 25 import android.preference.PreferenceScreen; 26 import android.preference.SwitchPreference; 27 import android.provider.Settings; 28 import android.support.annotation.Nullable; 29 import android.support.annotation.VisibleForTesting; 30 import android.telecom.PhoneAccount; 31 import android.telecom.PhoneAccountHandle; 32 import android.telecom.TelecomManager; 33 import android.telephony.SubscriptionInfo; 34 import android.telephony.TelephonyManager; 35 import com.android.dialer.common.Assert; 36 import com.android.dialer.common.LogUtil; 37 import com.android.dialer.logging.DialerImpression; 38 import com.android.dialer.logging.Logger; 39 import com.android.dialer.notification.NotificationChannelManager; 40 import com.android.dialer.telecom.TelecomUtil; 41 import com.android.voicemail.VoicemailClient; 42 import com.android.voicemail.VoicemailClient.ActivationStateListener; 43 import com.android.voicemail.VoicemailComponent; 44 import com.google.common.base.Optional; 45 46 /** 47 * Fragment for voicemail settings. Requires {@link VoicemailClient#PARAM_PHONE_ACCOUNT_HANDLE} set 48 * in arguments. 49 */ 50 @TargetApi(VERSION_CODES.O) 51 public class VoicemailSettingsFragment extends PreferenceFragment 52 implements Preference.OnPreferenceChangeListener, ActivationStateListener { 53 54 private static final String TAG = "VmSettingsActivity"; 55 56 // Extras copied from com.android.phone.settings.VoicemailSettingsActivity, 57 // it does not recognize EXTRA_PHONE_ACCOUNT_HANDLE in O. 58 @VisibleForTesting 59 static final String SUB_ID_EXTRA = 60 "com.android.phone.settings.SubscriptionInfoHelper.SubscriptionId"; 61 // Extra on intent containing the label of a subscription. 62 @VisibleForTesting 63 static final String SUB_LABEL_EXTRA = 64 "com.android.phone.settings.SubscriptionInfoHelper.SubscriptionLabel"; 65 66 @Nullable private PhoneAccountHandle phoneAccountHandle; 67 68 private VoicemailClient voicemailClient; 69 70 private Preference voicemailNotificationPreference; 71 private SwitchPreference voicemailVisualVoicemail; 72 private SwitchPreference autoArchiveSwitchPreference; 73 private SwitchPreference donateVoicemailSwitchPreference; 74 private Preference voicemailChangePinPreference; 75 private PreferenceScreen advancedSettings; 76 77 @Override onCreate(Bundle icicle)78 public void onCreate(Bundle icicle) { 79 super.onCreate(icicle); 80 81 phoneAccountHandle = 82 Assert.isNotNull(getArguments().getParcelable(VoicemailClient.PARAM_PHONE_ACCOUNT_HANDLE)); 83 voicemailClient = VoicemailComponent.get(getContext()).getVoicemailClient(); 84 } 85 86 @Override onResume()87 public void onResume() { 88 super.onResume(); 89 Logger.get(getContext()).logImpression(DialerImpression.Type.VVM_SETTINGS_VIEWED); 90 voicemailClient.addActivationStateListener(this); 91 PreferenceScreen preferenceScreen = getPreferenceScreen(); 92 if (preferenceScreen != null) { 93 preferenceScreen.removeAll(); 94 } 95 96 addPreferencesFromResource(R.xml.voicemail_settings); 97 98 PreferenceScreen prefSet = getPreferenceScreen(); 99 100 voicemailNotificationPreference = 101 findPreference(getString(R.string.voicemail_notifications_key)); 102 voicemailNotificationPreference.setIntent(getNotificationSettingsIntent()); 103 104 voicemailNotificationPreference.setOnPreferenceClickListener( 105 new OnPreferenceClickListener() { 106 @Override 107 public boolean onPreferenceClick(Preference preference) { 108 Logger.get(getContext()) 109 .logImpression(DialerImpression.Type.VVM_CHANGE_RINGTONE_CLICKED); 110 // Let the preference handle the click. 111 return false; 112 } 113 }); 114 115 voicemailVisualVoicemail = 116 (SwitchPreference) findPreference(getString(R.string.voicemail_visual_voicemail_key)); 117 118 autoArchiveSwitchPreference = 119 (SwitchPreference) 120 findPreference(getString(R.string.voicemail_visual_voicemail_archive_key)); 121 122 donateVoicemailSwitchPreference = 123 (SwitchPreference) 124 findPreference(getString(R.string.voicemail_visual_voicemail_donation_key)); 125 126 if (!VoicemailComponent.get(getContext()) 127 .getVoicemailClient() 128 .isVoicemailArchiveAvailable(getContext())) { 129 getPreferenceScreen().removePreference(autoArchiveSwitchPreference); 130 } 131 132 if (!VoicemailComponent.get(getContext()) 133 .getVoicemailClient() 134 .isVoicemailDonationAvailable(getContext())) { 135 getPreferenceScreen().removePreference(donateVoicemailSwitchPreference); 136 } 137 138 voicemailChangePinPreference = findPreference(getString(R.string.voicemail_change_pin_key)); 139 140 if (voicemailClient.hasCarrierSupport(getContext(), phoneAccountHandle)) { 141 Assert.isNotNull(phoneAccountHandle); 142 Intent changePinIntent = 143 new Intent(new Intent(getContext(), VoicemailChangePinActivity.class)); 144 changePinIntent.putExtra(VoicemailClient.PARAM_PHONE_ACCOUNT_HANDLE, phoneAccountHandle); 145 146 voicemailChangePinPreference.setIntent(changePinIntent); 147 voicemailChangePinPreference.setOnPreferenceClickListener( 148 new OnPreferenceClickListener() { 149 @Override 150 public boolean onPreferenceClick(Preference preference) { 151 Logger.get(getContext()).logImpression(DialerImpression.Type.VVM_CHANGE_PIN_CLICKED); 152 // Let the preference handle the click. 153 return false; 154 } 155 }); 156 if (VoicemailChangePinActivity.isPinScrambled(getContext(), phoneAccountHandle)) { 157 voicemailChangePinPreference.setTitle(R.string.voicemail_set_pin_preference_title); 158 } else { 159 voicemailChangePinPreference.setTitle(R.string.voicemail_change_pin_preference_title); 160 } 161 updateChangePin(); 162 163 voicemailVisualVoicemail.setOnPreferenceChangeListener(this); 164 voicemailVisualVoicemail.setChecked( 165 voicemailClient.isVoicemailEnabled(getContext(), phoneAccountHandle)); 166 167 autoArchiveSwitchPreference.setOnPreferenceChangeListener(this); 168 autoArchiveSwitchPreference.setChecked( 169 voicemailClient.isVoicemailArchiveEnabled(getContext(), phoneAccountHandle)); 170 171 donateVoicemailSwitchPreference.setOnPreferenceChangeListener(this); 172 donateVoicemailSwitchPreference.setChecked( 173 voicemailClient.isVoicemailDonationEnabled(getContext(), phoneAccountHandle)); 174 updateDonateVoicemail(); 175 } else { 176 prefSet.removePreference(voicemailVisualVoicemail); 177 prefSet.removePreference(autoArchiveSwitchPreference); 178 prefSet.removePreference(donateVoicemailSwitchPreference); 179 prefSet.removePreference(voicemailChangePinPreference); 180 } 181 182 advancedSettings = 183 (PreferenceScreen) findPreference(getString(R.string.voicemail_advanced_settings_key)); 184 Intent advancedSettingsIntent = new Intent(TelephonyManager.ACTION_CONFIGURE_VOICEMAIL); 185 advancedSettingsIntent.putExtra(TelephonyManager.EXTRA_HIDE_PUBLIC_SETTINGS, true); 186 advancedSettingsIntent.putExtra( 187 TelephonyManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle); 188 189 // (a bug): EXTRA_PHONE_ACCOUNT_HANDLE not implemented in telephony in O. 190 Optional<SubscriptionInfo> subscriptionInfo = 191 TelecomUtil.getSubscriptionInfo(getContext(), phoneAccountHandle); 192 if (subscriptionInfo.isPresent()) { 193 advancedSettingsIntent.putExtra(SUB_ID_EXTRA, subscriptionInfo.get().getSubscriptionId()); 194 PhoneAccount phoneAccount = 195 getContext().getSystemService(TelecomManager.class).getPhoneAccount(phoneAccountHandle); 196 if (phoneAccount != null) { 197 advancedSettingsIntent.putExtra(SUB_LABEL_EXTRA, phoneAccount.getLabel()); 198 } 199 } 200 201 advancedSettings.setIntent(advancedSettingsIntent); 202 voicemailChangePinPreference.setOnPreferenceClickListener( 203 new OnPreferenceClickListener() { 204 @Override 205 public boolean onPreferenceClick(Preference preference) { 206 Logger.get(getContext()) 207 .logImpression(DialerImpression.Type.VVM_ADVANCED_SETINGS_CLICKED); 208 // Let the preference handle the click. 209 return false; 210 } 211 }); 212 } 213 214 @Override onPause()215 public void onPause() { 216 voicemailClient.removeActivationStateListener(this); 217 super.onPause(); 218 } 219 220 /** 221 * Implemented to support onPreferenceChangeListener to look for preference changes. 222 * 223 * @param preference is the preference to be changed 224 * @param objValue should be the value of the selection, NOT its localized display value. 225 */ 226 @Override onPreferenceChange(Preference preference, Object objValue)227 public boolean onPreferenceChange(Preference preference, Object objValue) { 228 LogUtil.d(TAG, "onPreferenceChange: \"" + preference + "\" changed to \"" + objValue + "\""); 229 if (preference.getKey().equals(voicemailVisualVoicemail.getKey())) { 230 boolean isEnabled = (boolean) objValue; 231 if (!isEnabled) { 232 showDisableConfirmationDialog(); 233 // Don't let the preference setting proceed. 234 return false; 235 } else { 236 updateVoicemailEnabled(true); 237 } 238 } else if (preference.getKey().equals(autoArchiveSwitchPreference.getKey())) { 239 logArchiveToggle((boolean) objValue); 240 voicemailClient.setVoicemailArchiveEnabled( 241 getContext(), phoneAccountHandle, (boolean) objValue); 242 } else if (preference.getKey().equals(donateVoicemailSwitchPreference.getKey())) { 243 logArchiveToggle((boolean) objValue); 244 voicemailClient.setVoicemailDonationEnabled( 245 getContext(), phoneAccountHandle, (boolean) objValue); 246 } 247 248 // Let the preference setting proceed. 249 return true; 250 } 251 updateVoicemailEnabled(boolean isEnabled)252 private void updateVoicemailEnabled(boolean isEnabled) { 253 voicemailClient.setVoicemailEnabled(getContext(), phoneAccountHandle, isEnabled); 254 voicemailVisualVoicemail.setChecked(isEnabled); 255 256 if (isEnabled) { 257 Logger.get(getContext()).logImpression(DialerImpression.Type.VVM_USER_ENABLED_IN_SETTINGS); 258 } else { 259 Logger.get(getContext()).logImpression(DialerImpression.Type.VVM_USER_DISABLED_IN_SETTINGS); 260 } 261 262 updateChangePin(); 263 updateDonateVoicemail(); 264 } 265 updateChangePin()266 private void updateChangePin() { 267 if (!voicemailClient.isVoicemailEnabled(getContext(), phoneAccountHandle)) { 268 voicemailChangePinPreference.setSummary( 269 R.string.voicemail_change_pin_preference_summary_disable); 270 voicemailChangePinPreference.setEnabled(false); 271 } else if (!voicemailClient.isActivated(getContext(), phoneAccountHandle)) { 272 voicemailChangePinPreference.setSummary( 273 R.string.voicemail_change_pin_preference_summary_not_activated); 274 voicemailChangePinPreference.setEnabled(false); 275 } else { 276 voicemailChangePinPreference.setSummary(null); 277 voicemailChangePinPreference.setEnabled(true); 278 } 279 } 280 updateDonateVoicemail()281 private void updateDonateVoicemail() { 282 if (!voicemailClient.isVoicemailEnabled(getContext(), phoneAccountHandle)) { 283 donateVoicemailSwitchPreference.setSummary( 284 R.string.voicemail_donate_preference_summary_disable); 285 donateVoicemailSwitchPreference.setEnabled(false); 286 } else if (!voicemailClient.isActivated(getContext(), phoneAccountHandle)) { 287 donateVoicemailSwitchPreference.setSummary( 288 R.string.voicemail_donate_preference_summary_not_activated); 289 donateVoicemailSwitchPreference.setEnabled(false); 290 } else { 291 donateVoicemailSwitchPreference.setSummary(R.string.voicemail_donate_preference_summary_info); 292 donateVoicemailSwitchPreference.setEnabled(true); 293 } 294 } 295 logArchiveToggle(boolean userTurnedOn)296 private void logArchiveToggle(boolean userTurnedOn) { 297 if (userTurnedOn) { 298 Logger.get(getContext()) 299 .logImpression(DialerImpression.Type.VVM_USER_TURNED_ARCHIVE_ON_FROM_SETTINGS); 300 } else { 301 Logger.get(getContext()) 302 .logImpression(DialerImpression.Type.VVM_USER_TURNED_ARCHIVE_OFF_FROM_SETTINGS); 303 } 304 } 305 306 @Override onActivationStateChanged(PhoneAccountHandle phoneAccountHandle, boolean isActivated)307 public void onActivationStateChanged(PhoneAccountHandle phoneAccountHandle, boolean isActivated) { 308 if (this.phoneAccountHandle.equals(phoneAccountHandle)) { 309 updateChangePin(); 310 updateDonateVoicemail(); 311 } 312 } 313 getNotificationSettingsIntent()314 private Intent getNotificationSettingsIntent() { 315 String channelId = 316 NotificationChannelManager.getVoicemailChannelId(getContext(), phoneAccountHandle); 317 return new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) 318 .putExtra(Settings.EXTRA_CHANNEL_ID, channelId) 319 .putExtra(Settings.EXTRA_APP_PACKAGE, getContext().getPackageName()); 320 } 321 showDisableConfirmationDialog()322 private void showDisableConfirmationDialog() { 323 LogUtil.i(TAG, "showDisableConfirmationDialog"); 324 AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); 325 builder.setTitle(R.string.confirm_disable_voicemail_dialog_title); 326 builder.setMessage(R.string.confirm_disable_voicemail_dialog_message); 327 builder.setPositiveButton( 328 R.string.confirm_disable_voicemail_accept_dialog_label, 329 new DialogInterface.OnClickListener() { 330 @Override 331 public void onClick(DialogInterface dialog, int which) { 332 LogUtil.i(TAG, "showDisableConfirmationDialog, confirmed"); 333 updateVoicemailEnabled(false); 334 dialog.dismiss(); 335 } 336 }); 337 338 builder.setNegativeButton( 339 android.R.string.cancel, 340 new DialogInterface.OnClickListener() { 341 @Override 342 public void onClick(DialogInterface dialog, int which) { 343 LogUtil.i(TAG, "showDisableConfirmationDialog, cancelled"); 344 dialog.dismiss(); 345 } 346 }); 347 348 builder.setCancelable(true); 349 builder.show(); 350 } 351 } 352