Move voicemail settings to dialer UI

The voicemail module should not contain any UI code.

Bug: 37258159
Test: DialerSettingsActivityTest,VoicemailSettingsFragmentTest. A future CL is refactoring VoicemailChangePinActivity into a fragment.
PiperOrigin-RevId: 174125949
Change-Id: I89cf6a083b0a0952332440d76e7ae0cb1c801931
diff --git a/java/com/android/voicemail/PinChanger.java b/java/com/android/voicemail/PinChanger.java
new file mode 100644
index 0000000..f58c96b
--- /dev/null
+++ b/java/com/android/voicemail/PinChanger.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 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.voicemail;
+
+import android.support.annotation.IntDef;
+import android.support.annotation.WorkerThread;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/** Interface to change the PIN used to access the mailbox by calling. */
+public interface PinChanger {
+
+  /** Results from {@link #changePin(String, String)} */
+  @Retention(RetentionPolicy.SOURCE)
+  @IntDef(
+    value = {
+      CHANGE_PIN_SUCCESS,
+      CHANGE_PIN_TOO_SHORT,
+      CHANGE_PIN_TOO_LONG,
+      CHANGE_PIN_TOO_WEAK,
+      CHANGE_PIN_MISMATCH,
+      CHANGE_PIN_INVALID_CHARACTER,
+      CHANGE_PIN_SYSTEM_ERROR
+    }
+  )
+  @interface ChangePinResult {}
+
+  int CHANGE_PIN_SUCCESS = 0;
+  int CHANGE_PIN_TOO_SHORT = 1;
+  int CHANGE_PIN_TOO_LONG = 2;
+  int CHANGE_PIN_TOO_WEAK = 3;
+  int CHANGE_PIN_MISMATCH = 4;
+  int CHANGE_PIN_INVALID_CHARACTER = 5;
+  int CHANGE_PIN_SYSTEM_ERROR = 6;
+
+  @WorkerThread
+  @ChangePinResult
+  int changePin(String oldPin, String newPin);
+
+  /**
+   * Set the scrambled PIN if it is auto generated during provisioning. Set to {@code null} to
+   * clear.
+   */
+  void setScrambledPin(String pin);
+
+  String getScrambledPin();
+
+  /** Format requirements for the PIN. */
+  class PinSpecification {
+    public int minLength;
+    public int maxLength;
+  }
+
+  PinSpecification getPinSpecification();
+}
diff --git a/java/com/android/voicemail/VoicemailClient.java b/java/com/android/voicemail/VoicemailClient.java
index 717362e..d033369 100644
--- a/java/com/android/voicemail/VoicemailClient.java
+++ b/java/com/android/voicemail/VoicemailClient.java
@@ -17,7 +17,6 @@
 package com.android.voicemail;
 
 import android.content.Context;
-import android.content.Intent;
 import android.os.PersistableBundle;
 import android.provider.VoicemailContract.Voicemails;
 import android.support.annotation.MainThread;
@@ -67,6 +66,12 @@
   String VOICEMAIL_SECRET_CODE = "886266344";
 
   /**
+   * Whether visual voicemail is supported by the carrier for the {@code phoneAccountHandle}. This
+   * is purely based on the MCCMNC, and a single account might still be disabled by the carrier.
+   */
+  boolean hasCarrierSupport(Context context, PhoneAccountHandle phoneAccountHandle);
+
+  /**
    * Whether the visual voicemail service is enabled for the {@code phoneAccountHandle}. "Enable"
    * means the user "wants" to have this service on, and does not mean the service is actually
    * functional(For example, the service is blocked on the carrier side. The service will be
@@ -104,14 +109,6 @@
   void appendOmtpVoicemailStatusSelectionClause(
       Context context, StringBuilder where, List<String> selectionArgs);
 
-  /**
-   * @return the class name of the {@link android.preference.PreferenceFragment} for voicemail
-   *     settings, or {@code null} if dialer cannot control voicemail settings. Always return {@code
-   *     null} before OC.
-   */
-  @Nullable
-  String getSettingsFragment();
-
   boolean isVoicemailArchiveEnabled(Context context, PhoneAccountHandle phoneAccountHandle);
 
   /**
@@ -134,11 +131,8 @@
   /** @return if the voicemail donation setting has been enabled by the user. */
   boolean isVoicemailDonationEnabled(Context context, PhoneAccountHandle account);
 
-  /**
-   * @return an intent that will launch the activity to change the voicemail PIN. The PIN is used
-   *     when calling into the mailbox.
-   */
-  Intent getSetPinIntent(Context context, PhoneAccountHandle phoneAccountHandle);
+  void setVoicemailDonationEnabled(
+      Context context, PhoneAccountHandle phoneAccountHandle, boolean enabled);
 
   /**
    * Whether the client is activated and handling visual voicemail for the {@code
@@ -165,5 +159,20 @@
   @MainThread
   void onShutdown(@NonNull Context context);
 
+  /** Listener for changes in {@link #isActivated(Context, PhoneAccountHandle)} */
+  interface ActivationStateListener {
+    @MainThread
+    void onActivationStateChanged(PhoneAccountHandle phoneAccountHandle, boolean isActivated);
+  }
+
+  @MainThread
+  void addActivationStateListener(ActivationStateListener listener);
+
+  @MainThread
+  void removeActivationStateListener(ActivationStateListener listener);
+
+  /** Provides interface to change the PIN used to access the mailbox by calling. */
+  PinChanger createPinChanger(Context context, PhoneAccountHandle phoneAccountHandle);
+
   void onTosAccepted(Context context);
 }
diff --git a/java/com/android/voicemail/impl/OmtpConstants.java b/java/com/android/voicemail/impl/OmtpConstants.java
index 97da2a8..d94e361 100644
--- a/java/com/android/voicemail/impl/OmtpConstants.java
+++ b/java/com/android/voicemail/impl/OmtpConstants.java
@@ -13,11 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License
  */
-package com.android.voicemail.impl;
 
-import android.support.annotation.IntDef;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
+package com.android.voicemail.impl;
 
 /**
  * Wrapper class to hold relevant OMTP constants as defined in the OMTP spec.
@@ -212,28 +209,6 @@
   public static final String RESPONSE_CHANGE_PIN_INVALID_CHARACTER =
       "password contains invalid characters";
 
-  @Retention(RetentionPolicy.SOURCE)
-  @IntDef(
-    value = {
-      CHANGE_PIN_SUCCESS,
-      CHANGE_PIN_TOO_SHORT,
-      CHANGE_PIN_TOO_LONG,
-      CHANGE_PIN_TOO_WEAK,
-      CHANGE_PIN_MISMATCH,
-      CHANGE_PIN_INVALID_CHARACTER,
-      CHANGE_PIN_SYSTEM_ERROR
-    }
-  )
-  public @interface ChangePinResult {}
-
-  public static final int CHANGE_PIN_SUCCESS = 0;
-  public static final int CHANGE_PIN_TOO_SHORT = 1;
-  public static final int CHANGE_PIN_TOO_LONG = 2;
-  public static final int CHANGE_PIN_TOO_WEAK = 3;
-  public static final int CHANGE_PIN_MISMATCH = 4;
-  public static final int CHANGE_PIN_INVALID_CHARACTER = 5;
-  public static final int CHANGE_PIN_SYSTEM_ERROR = 6;
-
   public static String getClientType() {
     String manufacturer =
         truncate(
diff --git a/java/com/android/voicemail/impl/PinChangerImpl.java b/java/com/android/voicemail/impl/PinChangerImpl.java
new file mode 100644
index 0000000..8735a26
--- /dev/null
+++ b/java/com/android/voicemail/impl/PinChangerImpl.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2017 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.voicemail.impl;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.net.Network;
+import android.os.Build.VERSION_CODES;
+import android.support.annotation.WorkerThread;
+import android.telecom.PhoneAccountHandle;
+import com.android.dialer.common.Assert;
+import com.android.voicemail.PinChanger;
+import com.android.voicemail.impl.imap.ImapHelper;
+import com.android.voicemail.impl.imap.ImapHelper.InitializingException;
+import com.android.voicemail.impl.mail.MessagingException;
+import com.android.voicemail.impl.sync.VvmNetworkRequest;
+import com.android.voicemail.impl.sync.VvmNetworkRequest.NetworkWrapper;
+import com.android.voicemail.impl.sync.VvmNetworkRequest.RequestFailedException;
+
+@TargetApi(VERSION_CODES.O)
+class PinChangerImpl implements PinChanger {
+
+  private final Context context;
+  private final PhoneAccountHandle phoneAccountHandle;
+
+  private static final String KEY_SCRAMBLED_PIN = "default_old_pin"; // legacy name, DO NOT CHANGE
+
+  PinChangerImpl(Context context, PhoneAccountHandle phoneAccountHandle) {
+    this.context = context;
+    this.phoneAccountHandle = phoneAccountHandle;
+  }
+
+  @WorkerThread
+  @Override
+  @ChangePinResult
+  public int changePin(String oldPin, String newPin) {
+    Assert.isWorkerThread();
+    OmtpVvmCarrierConfigHelper config = new OmtpVvmCarrierConfigHelper(context, phoneAccountHandle);
+    VoicemailStatus.Editor status = VoicemailStatus.edit(context, phoneAccountHandle);
+    try (NetworkWrapper networkWrapper =
+        VvmNetworkRequest.getNetwork(config, phoneAccountHandle, status)) {
+      Network network = networkWrapper.get();
+      try (ImapHelper helper = new ImapHelper(context, phoneAccountHandle, network, status)) {
+        return helper.changePin(oldPin, newPin);
+      } catch (InitializingException | MessagingException e) {
+        VvmLog.e(
+            "VoicemailClientImpl.changePin", "ChangePinNetworkRequestCallback: onAvailable: " + e);
+        return PinChanger.CHANGE_PIN_SYSTEM_ERROR;
+      }
+
+    } catch (RequestFailedException e) {
+      return PinChanger.CHANGE_PIN_SYSTEM_ERROR;
+    }
+  }
+
+  @Override
+  public void setScrambledPin(String pin) {
+    new VisualVoicemailPreferences(context, phoneAccountHandle)
+        .edit()
+        .putString(KEY_SCRAMBLED_PIN, pin)
+        .apply();
+    if (pin == null) {
+      new OmtpVvmCarrierConfigHelper(context, phoneAccountHandle)
+          .handleEvent(
+              VoicemailStatus.edit(context, phoneAccountHandle), OmtpEvents.CONFIG_PIN_SET);
+    }
+  }
+
+  @Override
+  public String getScrambledPin() {
+    return new VisualVoicemailPreferences(context, phoneAccountHandle).getString(KEY_SCRAMBLED_PIN);
+  }
+
+  @Override
+  public PinSpecification getPinSpecification() {
+    PinSpecification result = new PinSpecification();
+    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 {
+        result.minLength = Integer.parseInt(lengths[0]);
+        result.maxLength = Integer.parseInt(lengths[1]);
+      } catch (NumberFormatException e) {
+        // do nothing, return default value;
+      }
+    }
+    return result;
+  }
+}
diff --git a/java/com/android/voicemail/impl/PreOMigrationHandler.java b/java/com/android/voicemail/impl/PreOMigrationHandler.java
index 6dc2dee..3ec5e08 100644
--- a/java/com/android/voicemail/impl/PreOMigrationHandler.java
+++ b/java/com/android/voicemail/impl/PreOMigrationHandler.java
@@ -22,8 +22,8 @@
 import android.telecom.PhoneAccountHandle;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import com.android.voicemail.VoicemailComponent;
 import com.android.voicemail.impl.settings.VisualVoicemailSettingsUtil;
-import com.android.voicemail.impl.settings.VoicemailChangePinActivity;
 import java.lang.reflect.Method;
 
 /** Handles migration of data from the visual voicemail client in telephony before O. */
@@ -95,7 +95,10 @@
       String scrambledPin = legacySettings.getString(EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING);
       if (!TextUtils.isEmpty(scrambledPin)) {
         VvmLog.i("PreOMigrationHandler.migrateSettings", "migrating scrambled PIN");
-        VoicemailChangePinActivity.setDefaultOldPIN(context, phoneAccountHandle, scrambledPin);
+        VoicemailComponent.get(context)
+            .getVoicemailClient()
+            .createPinChanger(context, phoneAccountHandle)
+            .setScrambledPin(scrambledPin);
       }
     }
   }
diff --git a/java/com/android/voicemail/impl/VoicemailClientImpl.java b/java/com/android/voicemail/impl/VoicemailClientImpl.java
index ff1a18d..14fa1d8 100644
--- a/java/com/android/voicemail/impl/VoicemailClientImpl.java
+++ b/java/com/android/voicemail/impl/VoicemailClientImpl.java
@@ -22,19 +22,17 @@
 import android.provider.VoicemailContract.Voicemails;
 import android.support.annotation.MainThread;
 import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 import android.support.v4.os.BuildCompat;
 import android.telecom.PhoneAccountHandle;
 import android.telephony.TelephonyManager;
 import com.android.dialer.common.Assert;
 import com.android.dialer.common.LogUtil;
 import com.android.dialer.configprovider.ConfigProviderBindings;
+import com.android.voicemail.PinChanger;
 import com.android.voicemail.VisualVoicemailTypeExtensions;
 import com.android.voicemail.VoicemailClient;
 import com.android.voicemail.impl.configui.VoicemailSecretCodeActivity;
 import com.android.voicemail.impl.settings.VisualVoicemailSettingsUtil;
-import com.android.voicemail.impl.settings.VoicemailChangePinActivity;
-import com.android.voicemail.impl.settings.VoicemailSettingsFragment;
 import com.android.voicemail.impl.sync.VvmAccountManager;
 import com.android.voicemail.impl.transcribe.TranscriptionBackfillService;
 import com.android.voicemail.impl.transcribe.TranscriptionConfigProvider;
@@ -75,6 +73,11 @@
   }
 
   @Override
+  public boolean hasCarrierSupport(Context context, PhoneAccountHandle phoneAccountHandle) {
+    return new OmtpVvmCarrierConfigHelper(context, phoneAccountHandle).isValid();
+  }
+
+  @Override
   public boolean isVoicemailEnabled(Context context, PhoneAccountHandle phoneAccountHandle) {
     return VisualVoicemailSettingsUtil.isEnabled(context, phoneAccountHandle);
   }
@@ -85,12 +88,6 @@
     VisualVoicemailSettingsUtil.setEnabled(context, phoneAccountHandle, enabled);
   }
 
-  @Nullable
-  @Override
-  public String getSettingsFragment() {
-    return VoicemailSettingsFragment.class.getName();
-  }
-
   @Override
   public boolean isVoicemailArchiveEnabled(Context context, PhoneAccountHandle phoneAccountHandle) {
     return VisualVoicemailSettingsUtil.isArchiveEnabled(context, phoneAccountHandle);
@@ -145,10 +142,9 @@
   }
 
   @Override
-  public Intent getSetPinIntent(Context context, PhoneAccountHandle phoneAccountHandle) {
-    Intent intent = new Intent(context, VoicemailChangePinActivity.class);
-    intent.putExtra(VoicemailChangePinActivity.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
-    return intent;
+  public void setVoicemailDonationEnabled(
+      Context context, PhoneAccountHandle phoneAccountHandle, boolean enabled) {
+    VisualVoicemailSettingsUtil.setVoicemailDonationEnabled(context, phoneAccountHandle, enabled);
   }
 
   @Override
@@ -181,6 +177,21 @@
     OmtpService.onShutdown(context);
   }
 
+  @Override
+  public void addActivationStateListener(ActivationStateListener listener) {
+    VvmAccountManager.addListener(listener);
+  }
+
+  @Override
+  public void removeActivationStateListener(ActivationStateListener listener) {
+    VvmAccountManager.removeListener(listener);
+  }
+
+  @Override
+  public PinChanger createPinChanger(Context context, PhoneAccountHandle phoneAccountHandle) {
+    return new PinChangerImpl(context, phoneAccountHandle);
+  }
+
   @TargetApi(VERSION_CODES.O)
   @Override
   public void appendOmtpVoicemailSelectionClause(
diff --git a/java/com/android/voicemail/impl/imap/ImapHelper.java b/java/com/android/voicemail/impl/imap/ImapHelper.java
index 94abe9b..a0e86dc 100644
--- a/java/com/android/voicemail/impl/imap/ImapHelper.java
+++ b/java/com/android/voicemail/impl/imap/ImapHelper.java
@@ -22,8 +22,9 @@
 import android.support.annotation.Nullable;
 import android.telecom.PhoneAccountHandle;
 import android.util.Base64;
+import com.android.voicemail.PinChanger;
+import com.android.voicemail.PinChanger.ChangePinResult;
 import com.android.voicemail.impl.OmtpConstants;
-import com.android.voicemail.impl.OmtpConstants.ChangePinResult;
 import com.android.voicemail.impl.OmtpEvents;
 import com.android.voicemail.impl.OmtpVvmCarrierConfigHelper;
 import com.android.voicemail.impl.VisualVoicemailPreferences;
@@ -393,7 +394,7 @@
       return getChangePinResultFromImapResponse(connection.readResponse());
     } catch (IOException ioe) {
       VvmLog.e(TAG, "changePin: ", ioe);
-      return OmtpConstants.CHANGE_PIN_SYSTEM_ERROR;
+      return PinChanger.CHANGE_PIN_SYSTEM_ERROR;
     } finally {
       connection.destroyResponses();
     }
@@ -434,24 +435,24 @@
       String message = response.getStringOrEmpty(1).getString();
       LogUtils.d(TAG, "change PIN failed: " + message);
       if (OmtpConstants.RESPONSE_CHANGE_PIN_TOO_SHORT.equals(message)) {
-        return OmtpConstants.CHANGE_PIN_TOO_SHORT;
+        return PinChanger.CHANGE_PIN_TOO_SHORT;
       }
       if (OmtpConstants.RESPONSE_CHANGE_PIN_TOO_LONG.equals(message)) {
-        return OmtpConstants.CHANGE_PIN_TOO_LONG;
+        return PinChanger.CHANGE_PIN_TOO_LONG;
       }
       if (OmtpConstants.RESPONSE_CHANGE_PIN_TOO_WEAK.equals(message)) {
-        return OmtpConstants.CHANGE_PIN_TOO_WEAK;
+        return PinChanger.CHANGE_PIN_TOO_WEAK;
       }
       if (OmtpConstants.RESPONSE_CHANGE_PIN_MISMATCH.equals(message)) {
-        return OmtpConstants.CHANGE_PIN_MISMATCH;
+        return PinChanger.CHANGE_PIN_MISMATCH;
       }
       if (OmtpConstants.RESPONSE_CHANGE_PIN_INVALID_CHARACTER.equals(message)) {
-        return OmtpConstants.CHANGE_PIN_INVALID_CHARACTER;
+        return PinChanger.CHANGE_PIN_INVALID_CHARACTER;
       }
-      return OmtpConstants.CHANGE_PIN_SYSTEM_ERROR;
+      return PinChanger.CHANGE_PIN_SYSTEM_ERROR;
     }
     LogUtils.d(TAG, "change PIN succeeded");
-    return OmtpConstants.CHANGE_PIN_SUCCESS;
+    return PinChanger.CHANGE_PIN_SUCCESS;
   }
 
   public void updateQuota() {
diff --git a/java/com/android/voicemail/impl/protocol/Vvm3EventHandler.java b/java/com/android/voicemail/impl/protocol/Vvm3EventHandler.java
index 24f530f..74ba8dd 100644
--- a/java/com/android/voicemail/impl/protocol/Vvm3EventHandler.java
+++ b/java/com/android/voicemail/impl/protocol/Vvm3EventHandler.java
@@ -20,13 +20,13 @@
 import android.provider.VoicemailContract.Status;
 import android.support.annotation.IntDef;
 import android.telecom.PhoneAccountHandle;
+import com.android.voicemail.VoicemailComponent;
 import com.android.voicemail.impl.DefaultOmtpEventHandler;
 import com.android.voicemail.impl.OmtpEvents;
 import com.android.voicemail.impl.OmtpEvents.Type;
 import com.android.voicemail.impl.OmtpVvmCarrierConfigHelper;
 import com.android.voicemail.impl.VoicemailStatus;
 import com.android.voicemail.impl.VvmLog;
-import com.android.voicemail.impl.settings.VoicemailChangePinActivity;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -302,6 +302,10 @@
       VvmLog.e(TAG, "status editor has null phone account handle");
       return false;
     }
-    return VoicemailChangePinActivity.isDefaultOldPinSet(context, phoneAccountHandle);
+    return VoicemailComponent.get(context)
+            .getVoicemailClient()
+            .createPinChanger(context, phoneAccountHandle)
+            .getScrambledPin()
+        != null;
   }
 }
diff --git a/java/com/android/voicemail/impl/protocol/Vvm3Protocol.java b/java/com/android/voicemail/impl/protocol/Vvm3Protocol.java
index 5454bac..782386d 100644
--- a/java/com/android/voicemail/impl/protocol/Vvm3Protocol.java
+++ b/java/com/android/voicemail/impl/protocol/Vvm3Protocol.java
@@ -26,6 +26,8 @@
 import android.telecom.PhoneAccountHandle;
 import android.text.TextUtils;
 import com.android.dialer.logging.DialerImpression;
+import com.android.voicemail.PinChanger;
+import com.android.voicemail.VoicemailComponent;
 import com.android.voicemail.impl.ActivationTask;
 import com.android.voicemail.impl.OmtpConstants;
 import com.android.voicemail.impl.OmtpEvents;
@@ -37,7 +39,6 @@
 import com.android.voicemail.impl.imap.ImapHelper.InitializingException;
 import com.android.voicemail.impl.mail.MessagingException;
 import com.android.voicemail.impl.settings.VisualVoicemailSettingsUtil;
-import com.android.voicemail.impl.settings.VoicemailChangePinActivity;
 import com.android.voicemail.impl.sms.OmtpMessageSender;
 import com.android.voicemail.impl.sms.StatusMessage;
 import com.android.voicemail.impl.sms.Vvm3MessageSender;
@@ -68,7 +69,7 @@
   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";
+  private static final String ISO639_SPANISH = "es";
 
   /**
    * For VVM3, if the STATUS SMS returns {@link StatusMessage#getProvisioningStatus()} of {@link
@@ -217,7 +218,7 @@
         // VVM3 has inconsistent error language code to OMTP. Just issue a raw command
         // here.
         // TODO(a bug): use LocaleList
-        if (Locale.getDefault().getLanguage().equals(new Locale(ISO639_Spanish).getLanguage())) {
+        if (Locale.getDefault().getLanguage().equals(new Locale(ISO639_SPANISH).getLanguage())) {
           // Spanish
           helper.changeVoicemailTuiLanguage(VVM3_VM_LANGUAGE_SPANISH_STANDARD_NO_GUEST_PROMPTS);
         } else {
@@ -257,14 +258,19 @@
       return false;
     }
 
-    if (VoicemailChangePinActivity.isDefaultOldPinSet(context, phoneAccountHandle)) {
+    PinChanger pinChanger =
+        VoicemailComponent.get(context)
+            .getVoicemailClient()
+            .createPinChanger(context, phoneAccountHandle);
+
+    if (pinChanger.getScrambledPin() != null) {
       // 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);
+    if (helper.changePin(defaultPin, newPin) == PinChanger.CHANGE_PIN_SUCCESS) {
+      pinChanger.setScrambledPin(newPin);
       helper.handleEvent(OmtpEvents.CONFIG_DEFAULT_PIN_REPLACED);
     }
     VvmLog.i(TAG, "new user: PIN set");
diff --git a/java/com/android/voicemail/impl/res/layout/voicemail_change_pin.xml b/java/com/android/voicemail/impl/res/layout/voicemail_change_pin.xml
deleted file mode 100644
index 50c9277..0000000
--- a/java/com/android/voicemail/impl/res/layout/voicemail_change_pin.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, 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.
-*/
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-  android:layout_width="match_parent"
-  android:layout_height="match_parent"
-  android:gravity="center_horizontal"
-  android:orientation="vertical">
-  <!-- header text ('Enter Pin') -->
-  <LinearLayout
-    android:layout_width="match_parent"
-    android:layout_height="0dp"
-    android:layout_weight="1"
-    android:orientation="vertical"
-    android:paddingTop="48dp"
-    android:paddingStart="48dp"
-    android:paddingEnd="48dp">
-    <TextView
-      android:id="@+id/headerText"
-      android:layout_width="match_parent"
-      android:layout_height="wrap_content"
-      android:gravity="center"
-      android:lines="2"
-      android:textAppearance="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle"
-      android:accessibilityLiveRegion="polite"/>
-
-    <!-- hint text ('PIN too short') -->
-    <TextView
-      android:id="@+id/hintText"
-      android:layout_width="match_parent"
-      android:layout_height="wrap_content"
-      android:gravity="center"
-      android:lines="2"/>
-
-    <!-- error text ('PIN too short') -->
-    <TextView
-      android:id="@+id/errorText"
-      android:layout_width="match_parent"
-      android:layout_height="wrap_content"
-      android:gravity="center"
-      android:lines="2"
-      android:textColor="@android:color/holo_red_dark"/>
-
-    <!-- Password entry field -->
-    <EditText
-      android:id="@+id/pin_entry"
-      android:layout_width="match_parent"
-      android:layout_height="wrap_content"
-      android:layout_gravity="center"
-      android:gravity="center"
-      android:imeOptions="actionNext|flagNoExtractUi"
-      android:inputType="numberPassword"
-      android:textSize="24sp"/>
-  </LinearLayout>
-
-  <LinearLayout
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:clipChildren="false"
-    android:clipToPadding="false"
-    android:gravity="end"
-    android:orientation="horizontal">
-
-    <!-- left : cancel -->
-    <Button
-      android:id="@+id/cancel_button"
-      android:layout_width="0dp"
-      android:layout_weight="1"
-      android:layout_height="wrap_content"
-      android:text="@string/change_pin_cancel_label"/>
-
-    <!-- right : continue -->
-    <Button
-      android:id="@+id/next_button"
-      android:layout_width="0dp"
-      android:layout_weight="1"
-      android:layout_height="wrap_content"
-      android:text="@string/change_pin_continue_label"/>
-
-  </LinearLayout>
-</LinearLayout>
diff --git a/java/com/android/voicemail/impl/res/values/strings.xml b/java/com/android/voicemail/impl/res/values/strings.xml
index c70306d..d1186c2 100644
--- a/java/com/android/voicemail/impl/res/values/strings.xml
+++ b/java/com/android/voicemail/impl/res/values/strings.xml
@@ -15,112 +15,9 @@
 -->
 
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-  <!-- Title of the "Voicemail" settings screen, with a text label identifying which SIM the settings are for. -->
-  <string name="voicemail_settings_with_label">Voicemail (<xliff:g example="Mock Carrier" id="subscriptionlabel">%s</xliff:g>)</string>
-
-  <!-- Call settings screen, setting option name -->
-  <string name="voicemail_settings_title">Voicemail</string>
-
-  <!-- DO NOT TRANSLATE. Internal key for a voicemail notification preference. -->
-  <string name="voicemail_notifications_key" translatable="false">voicemail_notification_key</string>
-
-  <!-- Voicemail notifications title. The user clicks on this preference to select
-         which sound to play and whether to vibrate when a voicemail notification is received.
-         [CHAR LIMIT=30] -->
-  <string name="voicemail_notifications_preference_title">Notifications</string>
-  <string name="voicemail_advanced_settings_key" translatable="false">voicemail_advanced_settings_key</string>
-
-  <!-- Title for advanced settings in the voicemail settings -->
-  <string name="voicemail_advanced_settings_title">Advanced Settings</string>
-
-  <!-- DO NOT TRANSLATE. Internal key for a visual voicemail preference. -->
-    <string name="voicemail_visual_voicemail_key" translatable="false">
-        voicemail_visual_voicemail_key
-    </string>
-  <!-- DO NOT TRANSLATE. Internal key for a visual voicemail archive preference. -->
-    <string name="voicemail_visual_voicemail_archive_key" translatable="false">
-        archive_is_enabled
-    </string>
-    <string name="voicemail_visual_voicemail_donation_key" translatable="false">
-        donate_voicemails
-    </string>
-  <!-- DO NOT TRANSLATE. Internal key for a voicemail change pin preference. -->
-  <string name="voicemail_change_pin_key" translatable="false">voicemail_change_pin_key</string>
-
-  <!-- Visual voicemail on/off title [CHAR LIMIT=40] -->
-  <string name="voicemail_visual_voicemail_switch_title">Visual Voicemail</string>
-
-  <!-- Visual voicemail archive on/off title [CHAR LIMIT=40] -->
-  <string name="voicemail_visual_voicemail_auto_archive_switch_title">
-    Extra backup and storage
-  </string>
-
-  <!-- Title for visual voicemail setting that enables user to donate their voicemails for analysis.
-       [CHAR LIMIT=40] -->
-  <string name="voicemail_visual_voicemail_donation_switch_title">
-    Voicemail transcription analysis
-  </string>
-  <!-- Summary information for visual voicemail donation setting when visual voicemail is not enabled
-       [CHAR LIMIT=NONE] -->
-  <string name="voicemail_donate_preference_summary_disable">Visual voicemail must be enabled to donate voicemails</string>
-  <!-- Summary information for visual voicemail donation setting when visual voicemail is not activated
-       [CHAR LIMIT=NONE] -->
-  <string name="voicemail_donate_preference_summary_not_activated">Visual voicemail is not activated yet, please try again later</string>
-  <!-- Summary information for visual voicemail donation setting [CHAR LIMIT=NONE] -->
-  <string name="voicemail_donate_preference_summary_info">Let Google review your voicemail messages to improve transcription quality</string>
-
-  <!-- Voicemail change PIN dialog title [CHAR LIMIT=40] -->
-  <string name="voicemail_set_pin_preference_title">Set PIN</string>
-  <!-- Voicemail change PIN dialog title [CHAR LIMIT=40] -->
-  <string name="voicemail_change_pin_preference_title">Change PIN</string>
-
-  <string name="voicemail_change_pin_preference_summary_disable">Visual voicemail must be enabled to change PIN</string>
-  <string name="voicemail_change_pin_preference_summary_not_activated">Visual voicemail is not activated yet, please try again later</string>
-
-  <!-- Message on the dialog when PIN changing is in progress -->
-  <string name="vm_change_pin_progress_message">Please wait.</string>
-  <!-- Error message for the voicemail PIN change if the PIN is too short -->
-  <string name="vm_change_pin_error_too_short">The new PIN is too short.</string>
-  <!-- Error message for the voicemail PIN change if the PIN is too long -->
-  <string name="vm_change_pin_error_too_long">The new PIN is too long.</string>
-  <!-- Error message for the voicemail PIN change if the PIN is too weak -->
-  <string name="vm_change_pin_error_too_weak">The new PIN is too weak. A strong password should not have continuous sequence or repeated digits.</string>
-  <!-- Error message for the voicemail PIN change if the old PIN entered doesn't match  -->
-  <string name="vm_change_pin_error_mismatch">The old PIN does not match.</string>
-  <!-- Error message for the voicemail PIN change if the new PIN contains invalid character -->
-  <string name="vm_change_pin_error_invalid">The new PIN contains invalid characters.</string>
-  <!-- Error message for the voicemail PIN change if operation has failed -->
-  <string name="vm_change_pin_error_system_error">Unable to change PIN</string>
   <!-- Message to replace the transcription if a visual voicemail message is not supported-->
   <string name="vvm_unsupported_message_format">Unsupported message type, call <xliff:g example="*86" id="number">%s</xliff:g> to listen.</string>
 
-  <!-- The title for the change voicemail PIN activity -->
-  <string name="change_pin_title">Change Voicemail PIN</string>
-  <!-- The label for the continue button in change voicemail PIN activity -->
-  <string name="change_pin_continue_label">Continue</string>
-  <!-- The label for the cancel button in change voicemail PIN activity -->
-  <string name="change_pin_cancel_label">Cancel</string>
-  <!-- The label for the ok button in change voicemail PIN activity -->
-  <string name="change_pin_ok_label">Ok</string>
-  <!-- The title for the enter old pin step in change voicemail PIN activity -->
-  <string name="change_pin_enter_old_pin_header">Confirm your old PIN</string>
-  <!-- The hint for the enter old pin step in change voicemail PIN activity -->
-  <string name="change_pin_enter_old_pin_hint">Enter your voicemail PIN to continue.</string>
-  <!-- The title for the enter new pin step in change voicemail PIN activity -->
-  <string name="change_pin_enter_new_pin_header">Set a new PIN</string>
-  <!-- The hint for the enter new pin step in change voicemail PIN activity -->
-  <string name="change_pin_enter_new_pin_hint">PIN must be <xliff:g example="4" id="min">%1$d</xliff:g>-<xliff:g example="7" id="max">%2$d</xliff:g> digits.</string>
-  <!-- The title for the confirm new pin step in change voicemail PIN activity -->
-  <string name="change_pin_confirm_pin_header">Confirm your PIN</string>
-  <!-- The error message for th confirm new pin step in change voicemail PIN activity, if the pin doen't match the one previously entered -->
-  <string name="change_pin_confirm_pins_dont_match">PINs don\'t match</string>
-  <!-- The toast to show after the voicemail PIN has been successfully changed -->
-  <string name="change_pin_succeeded">Voicemail PIN updated</string>
-  <!-- The error message to show if the server reported an error while attempting to change the voicemail PIN -->
-  <string name="change_pin_system_error">Unable to set PIN</string>
-
   <string name="vvm_config_override_load_current_key" translatable="false">vvm_config_override_load_current</string>
   <string name="vvm_config_override_enabled_key" translatable="false">vvm_config_override_enabled</string>
-
 </resources>
diff --git a/java/com/android/voicemail/impl/res/xml/voicemail_settings.xml b/java/com/android/voicemail/impl/res/xml/voicemail_settings.xml
deleted file mode 100644
index 9b0391a..0000000
--- a/java/com/android/voicemail/impl/res/xml/voicemail_settings.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 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.
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-  android:title="@string/voicemail_settings_title">
-
-  <Preference
-      android:key="@string/voicemail_notifications_key"
-      android:title="@string/voicemail_notifications_preference_title"/>
-
-  <SwitchPreference
-    android:key="@string/voicemail_visual_voicemail_key"
-    android:title="@string/voicemail_visual_voicemail_switch_title"/>"
-
-  <SwitchPreference
-    android:key="@string/voicemail_visual_voicemail_archive_key"
-    android:dependency="@string/voicemail_visual_voicemail_key"
-    android:title="@string/voicemail_visual_voicemail_auto_archive_switch_title"/>"
-
-  <SwitchPreference
-    android:key="@string/voicemail_visual_voicemail_donation_key"
-    android:dependency="@string/voicemail_visual_voicemail_key"
-    android:title="@string/voicemail_visual_voicemail_donation_switch_title"/>"
-
-  <Preference
-    android:key="@string/voicemail_change_pin_key"
-    android:title="@string/voicemail_change_pin_preference_title"/>
-
-  <PreferenceScreen
-    android:key="@string/voicemail_advanced_settings_key"
-    android:title="@string/voicemail_advanced_settings_title">
-    </PreferenceScreen>
-</PreferenceScreen>
diff --git a/java/com/android/voicemail/impl/settings/VisualVoicemailSettingsUtil.java b/java/com/android/voicemail/impl/settings/VisualVoicemailSettingsUtil.java
index 6694a5d..61d7619 100644
--- a/java/com/android/voicemail/impl/settings/VisualVoicemailSettingsUtil.java
+++ b/java/com/android/voicemail/impl/settings/VisualVoicemailSettingsUtil.java
@@ -21,7 +21,6 @@
 import com.android.dialer.common.Assert;
 import com.android.voicemail.VoicemailComponent;
 import com.android.voicemail.impl.OmtpVvmCarrierConfigHelper;
-import com.android.voicemail.impl.R;
 import com.android.voicemail.impl.VisualVoicemailPreferences;
 import com.android.voicemail.impl.VvmLog;
 import com.android.voicemail.impl.sync.VvmAccountManager;
@@ -30,6 +29,8 @@
 public class VisualVoicemailSettingsUtil {
 
   @VisibleForTesting public static final String IS_ENABLED_KEY = "is_enabled";
+  private static final String ARCHIVE_ENABLED_KEY = "archive_is_enabled";
+  private static final String DONATE_VOICEMAILS_KEY = "donate_voicemails";
 
   public static void setEnabled(
       Context context, PhoneAccountHandle phoneAccount, boolean isEnabled) {
@@ -53,7 +54,7 @@
         VoicemailComponent.get(context).getVoicemailClient().isVoicemailArchiveAvailable(context));
     new VisualVoicemailPreferences(context, phoneAccount)
         .edit()
-        .putBoolean(context.getString(R.string.voicemail_visual_voicemail_archive_key), isEnabled)
+        .putBoolean(ARCHIVE_ENABLED_KEY, isEnabled)
         .apply();
   }
 
@@ -65,7 +66,7 @@
             .isVoicemailTranscriptionAvailable(context));
     new VisualVoicemailPreferences(context, phoneAccount)
         .edit()
-        .putBoolean(context.getString(R.string.voicemail_visual_voicemail_donation_key), isEnabled)
+        .putBoolean(DONATE_VOICEMAILS_KEY, isEnabled)
         .apply();
   }
 
@@ -87,8 +88,7 @@
     Assert.isNotNull(phoneAccount);
 
     VisualVoicemailPreferences prefs = new VisualVoicemailPreferences(context, phoneAccount);
-    return prefs.getBoolean(
-        context.getString(R.string.voicemail_visual_voicemail_archive_key), false);
+    return prefs.getBoolean(ARCHIVE_ENABLED_KEY, false);
   }
 
   public static boolean isVoicemailDonationEnabled(
@@ -96,8 +96,7 @@
     Assert.isNotNull(phoneAccount);
 
     VisualVoicemailPreferences prefs = new VisualVoicemailPreferences(context, phoneAccount);
-    return prefs.getBoolean(
-        context.getString(R.string.voicemail_visual_voicemail_donation_key), false);
+    return prefs.getBoolean(DONATE_VOICEMAILS_KEY, false);
   }
 
   /**
diff --git a/java/com/android/voicemail/impl/settings/VoicemailChangePinActivity.java b/java/com/android/voicemail/impl/settings/VoicemailChangePinActivity.java
deleted file mode 100644
index b22a765..0000000
--- a/java/com/android/voicemail/impl/settings/VoicemailChangePinActivity.java
+++ /dev/null
@@ -1,627 +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.voicemail.impl.settings;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnDismissListener;
-import android.net.Network;
-import android.os.Build.VERSION_CODES;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.support.annotation.Nullable;
-import android.telecom.PhoneAccountHandle;
-import android.text.Editable;
-import android.text.InputFilter;
-import android.text.InputFilter.LengthFilter;
-import android.text.TextWatcher;
-import android.view.KeyEvent;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.WindowManager;
-import android.view.inputmethod.EditorInfo;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.TextView;
-import android.widget.TextView.OnEditorActionListener;
-import android.widget.Toast;
-import com.android.dialer.logging.DialerImpression;
-import com.android.voicemail.impl.OmtpConstants;
-import com.android.voicemail.impl.OmtpConstants.ChangePinResult;
-import com.android.voicemail.impl.OmtpEvents;
-import com.android.voicemail.impl.OmtpVvmCarrierConfigHelper;
-import com.android.voicemail.impl.R;
-import com.android.voicemail.impl.VisualVoicemailPreferences;
-import com.android.voicemail.impl.VoicemailStatus;
-import com.android.voicemail.impl.VvmLog;
-import com.android.voicemail.impl.imap.ImapHelper;
-import com.android.voicemail.impl.imap.ImapHelper.InitializingException;
-import com.android.voicemail.impl.mail.MessagingException;
-import com.android.voicemail.impl.sync.VvmNetworkRequestCallback;
-import com.android.voicemail.impl.utils.LoggerUtils;
-
-/**
- * Dialog to change the voicemail PIN. The TUI (Telephony User Interface) PIN is used when accessing
- * traditional voicemail through phone call. The intent to launch this activity must contain {@link
- * #EXTRA_PHONE_ACCOUNT_HANDLE}
- */
-@TargetApi(VERSION_CODES.O)
-public class VoicemailChangePinActivity extends Activity
-    implements OnClickListener, OnEditorActionListener, TextWatcher {
-
-  private static final String TAG = "VmChangePinActivity";
-
-  public static final String EXTRA_PHONE_ACCOUNT_HANDLE = "extra_phone_account_handle";
-
-  private static final String KEY_DEFAULT_OLD_PIN = "default_old_pin";
-
-  private static final int MESSAGE_HANDLE_RESULT = 1;
-
-  private PhoneAccountHandle mPhoneAccountHandle;
-  private OmtpVvmCarrierConfigHelper mConfig;
-
-  private int mPinMinLength;
-  private int mPinMaxLength;
-
-  private State mUiState = State.Initial;
-  private String mOldPin;
-  private String mFirstPin;
-
-  private ProgressDialog mProgressDialog;
-
-  private TextView mHeaderText;
-  private TextView mHintText;
-  private TextView mErrorText;
-  private EditText mPinEntry;
-  private Button mCancelButton;
-  private Button mNextButton;
-
-  private Handler mHandler =
-      new Handler() {
-        @Override
-        public void handleMessage(Message message) {
-          if (message.what == MESSAGE_HANDLE_RESULT) {
-            mUiState.handleResult(VoicemailChangePinActivity.this, message.arg1);
-          }
-        }
-      };
-
-  private enum State {
-    /**
-     * Empty state to handle initial state transition. Will immediately switch into {@link
-     * #VerifyOldPin} if a default PIN has been set by the OMTP client, or {@link #EnterOldPin} if
-     * not.
-     */
-    Initial,
-    /**
-     * Prompt the user to enter old PIN. The PIN will be verified with the server before proceeding
-     * to {@link #EnterNewPin}.
-     */
-    EnterOldPin {
-      @Override
-      public void onEnter(VoicemailChangePinActivity activity) {
-        activity.setHeader(R.string.change_pin_enter_old_pin_header);
-        activity.mHintText.setText(R.string.change_pin_enter_old_pin_hint);
-        activity.mNextButton.setText(R.string.change_pin_continue_label);
-        activity.mErrorText.setText(null);
-      }
-
-      @Override
-      public void onInputChanged(VoicemailChangePinActivity activity) {
-        activity.setNextEnabled(activity.getCurrentPasswordInput().length() > 0);
-      }
-
-      @Override
-      public void handleNext(VoicemailChangePinActivity activity) {
-        activity.mOldPin = activity.getCurrentPasswordInput();
-        activity.verifyOldPin();
-      }
-
-      @Override
-      public void handleResult(VoicemailChangePinActivity activity, @ChangePinResult int result) {
-        if (result == OmtpConstants.CHANGE_PIN_SUCCESS) {
-          activity.updateState(State.EnterNewPin);
-        } else {
-          CharSequence message = activity.getChangePinResultMessage(result);
-          activity.showError(message);
-          activity.mPinEntry.setText("");
-        }
-      }
-    },
-    /**
-     * The default old PIN is found. Show a blank screen while verifying with the server to make
-     * sure the PIN is still valid. If the PIN is still valid, proceed to {@link #EnterNewPin}. If
-     * not, the user probably changed the PIN through other means, proceed to {@link #EnterOldPin}.
-     * If any other issue caused the verifying to fail, show an error and exit.
-     */
-    VerifyOldPin {
-      @Override
-      public void onEnter(VoicemailChangePinActivity activity) {
-        activity.findViewById(android.R.id.content).setVisibility(View.INVISIBLE);
-        activity.verifyOldPin();
-      }
-
-      @Override
-      public void handleResult(
-          final VoicemailChangePinActivity activity, @ChangePinResult int result) {
-        if (result == OmtpConstants.CHANGE_PIN_SUCCESS) {
-          activity.updateState(State.EnterNewPin);
-        } else if (result == OmtpConstants.CHANGE_PIN_SYSTEM_ERROR) {
-          activity
-              .getWindow()
-              .setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
-          activity.showError(
-              activity.getString(R.string.change_pin_system_error),
-              new OnDismissListener() {
-                @Override
-                public void onDismiss(DialogInterface dialog) {
-                  activity.finish();
-                }
-              });
-        } else {
-          VvmLog.e(TAG, "invalid default old PIN: " + activity.getChangePinResultMessage(result));
-          // If the default old PIN is rejected by the server, the PIN is probably changed
-          // through other means, or the generated pin is invalid
-          // Wipe the default old PIN so the old PIN input box will be shown to the user
-          // on the next time.
-          setDefaultOldPIN(activity, activity.mPhoneAccountHandle, null);
-          activity.handleOmtpEvent(OmtpEvents.CONFIG_PIN_SET);
-          activity.updateState(State.EnterOldPin);
-        }
-      }
-
-      @Override
-      public void onLeave(VoicemailChangePinActivity activity) {
-        activity.findViewById(android.R.id.content).setVisibility(View.VISIBLE);
-      }
-    },
-    /**
-     * Let the user enter the new PIN and validate the format. Only length is enforced, PIN strength
-     * check relies on the server. After a valid PIN is entered, proceed to {@link #ConfirmNewPin}
-     */
-    EnterNewPin {
-      @Override
-      public void onEnter(VoicemailChangePinActivity activity) {
-        activity.mHeaderText.setText(R.string.change_pin_enter_new_pin_header);
-        activity.mNextButton.setText(R.string.change_pin_continue_label);
-        activity.mHintText.setText(
-            activity.getString(
-                R.string.change_pin_enter_new_pin_hint,
-                activity.mPinMinLength,
-                activity.mPinMaxLength));
-      }
-
-      @Override
-      public void onInputChanged(VoicemailChangePinActivity activity) {
-        String password = activity.getCurrentPasswordInput();
-        if (password.length() == 0) {
-          activity.setNextEnabled(false);
-          return;
-        }
-        CharSequence error = activity.validatePassword(password);
-        if (error != null) {
-          activity.mErrorText.setText(error);
-          activity.setNextEnabled(false);
-        } else {
-          activity.mErrorText.setText(null);
-          activity.setNextEnabled(true);
-        }
-      }
-
-      @Override
-      public void handleNext(VoicemailChangePinActivity activity) {
-        CharSequence errorMsg;
-        errorMsg = activity.validatePassword(activity.getCurrentPasswordInput());
-        if (errorMsg != null) {
-          activity.showError(errorMsg);
-          return;
-        }
-        activity.mFirstPin = activity.getCurrentPasswordInput();
-        activity.updateState(State.ConfirmNewPin);
-      }
-    },
-    /**
-     * Let the user type in the same PIN again to avoid typos. If the PIN matches then perform a PIN
-     * change to the server. Finish the activity if succeeded. Return to {@link #EnterOldPin} if the
-     * old PIN is rejected, {@link #EnterNewPin} for other failure.
-     */
-    ConfirmNewPin {
-      @Override
-      public void onEnter(VoicemailChangePinActivity activity) {
-        activity.mHeaderText.setText(R.string.change_pin_confirm_pin_header);
-        activity.mHintText.setText(null);
-        activity.mNextButton.setText(R.string.change_pin_ok_label);
-      }
-
-      @Override
-      public void onInputChanged(VoicemailChangePinActivity activity) {
-        if (activity.getCurrentPasswordInput().length() == 0) {
-          activity.setNextEnabled(false);
-          return;
-        }
-        if (activity.getCurrentPasswordInput().equals(activity.mFirstPin)) {
-          activity.setNextEnabled(true);
-          activity.mErrorText.setText(null);
-        } else {
-          activity.setNextEnabled(false);
-          activity.mErrorText.setText(R.string.change_pin_confirm_pins_dont_match);
-        }
-      }
-
-      @Override
-      public void handleResult(VoicemailChangePinActivity activity, @ChangePinResult int result) {
-        if (result == OmtpConstants.CHANGE_PIN_SUCCESS) {
-          // If the PIN change succeeded we no longer know what the old (current) PIN is.
-          // Wipe the default old PIN so the old PIN input box will be shown to the user
-          // on the next time.
-          setDefaultOldPIN(activity, activity.mPhoneAccountHandle, null);
-          activity.handleOmtpEvent(OmtpEvents.CONFIG_PIN_SET);
-
-          activity.finish();
-          LoggerUtils.logImpressionOnMainThread(
-              activity, DialerImpression.Type.VVM_CHANGE_PIN_COMPLETED);
-          Toast.makeText(
-                  activity, activity.getString(R.string.change_pin_succeeded), Toast.LENGTH_SHORT)
-              .show();
-        } else {
-          CharSequence message = activity.getChangePinResultMessage(result);
-          VvmLog.i(TAG, "Change PIN failed: " + message);
-          activity.showError(message);
-          if (result == OmtpConstants.CHANGE_PIN_MISMATCH) {
-            // Somehow the PIN has changed, prompt to enter the old PIN again.
-            activity.updateState(State.EnterOldPin);
-          } else {
-            // The new PIN failed to fulfil other restrictions imposed by the server.
-            activity.updateState(State.EnterNewPin);
-          }
-        }
-      }
-
-      @Override
-      public void handleNext(VoicemailChangePinActivity activity) {
-        activity.processPinChange(activity.mOldPin, activity.mFirstPin);
-      }
-    };
-
-    /** The activity has switched from another state to this one. */
-    public void onEnter(VoicemailChangePinActivity activity) {
-      // Do nothing
-    }
-
-    /**
-     * The user has typed something into the PIN input field. Also called after {@link
-     * #onEnter(VoicemailChangePinActivity)}
-     */
-    public void onInputChanged(VoicemailChangePinActivity activity) {
-      // Do nothing
-    }
-
-    /** The asynchronous call to change the PIN on the server has returned. */
-    public void handleResult(VoicemailChangePinActivity activity, @ChangePinResult int result) {
-      // Do nothing
-    }
-
-    /** The user has pressed the "next" button. */
-    public void handleNext(VoicemailChangePinActivity activity) {
-      // Do nothing
-    }
-
-    /** The activity has switched from this state to another one. */
-    public void onLeave(VoicemailChangePinActivity activity) {
-      // Do nothing
-    }
-  }
-
-  @Override
-  public void onCreate(Bundle savedInstanceState) {
-    super.onCreate(savedInstanceState);
-
-    mPhoneAccountHandle = getIntent().getParcelableExtra(EXTRA_PHONE_ACCOUNT_HANDLE);
-    mConfig = new OmtpVvmCarrierConfigHelper(this, mPhoneAccountHandle);
-    setContentView(R.layout.voicemail_change_pin);
-    setTitle(R.string.change_pin_title);
-
-    readPinLength();
-
-    View view = findViewById(android.R.id.content);
-
-    mCancelButton = (Button) view.findViewById(R.id.cancel_button);
-    mCancelButton.setOnClickListener(this);
-    mNextButton = (Button) view.findViewById(R.id.next_button);
-    mNextButton.setOnClickListener(this);
-
-    mPinEntry = (EditText) view.findViewById(R.id.pin_entry);
-    mPinEntry.setOnEditorActionListener(this);
-    mPinEntry.addTextChangedListener(this);
-    if (mPinMaxLength != 0) {
-      mPinEntry.setFilters(new InputFilter[] {new LengthFilter(mPinMaxLength)});
-    }
-
-    mHeaderText = (TextView) view.findViewById(R.id.headerText);
-    mHintText = (TextView) view.findViewById(R.id.hintText);
-    mErrorText = (TextView) view.findViewById(R.id.errorText);
-
-    if (isDefaultOldPinSet(this, mPhoneAccountHandle)) {
-      mOldPin = getDefaultOldPin(this, mPhoneAccountHandle);
-      updateState(State.VerifyOldPin);
-    } else {
-      updateState(State.EnterOldPin);
-    }
-  }
-
-  private void handleOmtpEvent(OmtpEvents event) {
-    mConfig.handleEvent(getVoicemailStatusEditor(), event);
-  }
-
-  private VoicemailStatus.Editor getVoicemailStatusEditor() {
-    // This activity does not have any automatic retry mechanism, errors should be written right
-    // away.
-    return VoicemailStatus.edit(this, mPhoneAccountHandle);
-  }
-
-  /** Extracts the pin length requirement sent by the server with a STATUS SMS. */
-  private void readPinLength() {
-    VisualVoicemailPreferences preferences =
-        new VisualVoicemailPreferences(this, mPhoneAccountHandle);
-    // The OMTP pin length format is {min}-{max}
-    String[] lengths = preferences.getString(OmtpConstants.TUI_PASSWORD_LENGTH, "").split("-");
-    if (lengths.length == 2) {
-      try {
-        mPinMinLength = Integer.parseInt(lengths[0]);
-        mPinMaxLength = Integer.parseInt(lengths[1]);
-      } catch (NumberFormatException e) {
-        mPinMinLength = 0;
-        mPinMaxLength = 0;
-      }
-    } else {
-      mPinMinLength = 0;
-      mPinMaxLength = 0;
-    }
-  }
-
-  @Override
-  public void onResume() {
-    super.onResume();
-    updateState(mUiState);
-  }
-
-  public void handleNext() {
-    if (mPinEntry.length() == 0) {
-      return;
-    }
-    mUiState.handleNext(this);
-  }
-
-  @Override
-  public void onClick(View v) {
-    if (v.getId() == R.id.next_button) {
-      handleNext();
-    } else if (v.getId() == R.id.cancel_button) {
-      finish();
-    }
-  }
-
-  @Override
-  public boolean onOptionsItemSelected(MenuItem item) {
-    if (item.getItemId() == android.R.id.home) {
-      onBackPressed();
-      return true;
-    }
-    return super.onOptionsItemSelected(item);
-  }
-
-  @Override
-  public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
-    if (!mNextButton.isEnabled()) {
-      return true;
-    }
-    // Check if this was the result of hitting the enter or "done" key
-    if (actionId == EditorInfo.IME_NULL
-        || actionId == EditorInfo.IME_ACTION_DONE
-        || actionId == EditorInfo.IME_ACTION_NEXT) {
-      handleNext();
-      return true;
-    }
-    return false;
-  }
-
-  @Override
-  public void afterTextChanged(Editable s) {
-    mUiState.onInputChanged(this);
-  }
-
-  @Override
-  public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-    // Do nothing
-  }
-
-  @Override
-  public void onTextChanged(CharSequence s, int start, int before, int count) {
-    // Do nothing
-  }
-
-  /**
-   * After replacing the default PIN with a random PIN, call this to store the random PIN. The
-   * stored PIN will be automatically entered when the user attempts to change the PIN.
-   */
-  public static void setDefaultOldPIN(
-      Context context, PhoneAccountHandle phoneAccountHandle, String pin) {
-    new VisualVoicemailPreferences(context, phoneAccountHandle)
-        .edit()
-        .putString(KEY_DEFAULT_OLD_PIN, pin)
-        .apply();
-  }
-
-  public static boolean isDefaultOldPinSet(Context context, PhoneAccountHandle phoneAccountHandle) {
-    return getDefaultOldPin(context, phoneAccountHandle) != null;
-  }
-
-  private static String getDefaultOldPin(Context context, PhoneAccountHandle phoneAccountHandle) {
-    return new VisualVoicemailPreferences(context, phoneAccountHandle)
-        .getString(KEY_DEFAULT_OLD_PIN);
-  }
-
-  private String getCurrentPasswordInput() {
-    return mPinEntry.getText().toString();
-  }
-
-  private void updateState(State state) {
-    State previousState = mUiState;
-    mUiState = state;
-    if (previousState != state) {
-      previousState.onLeave(this);
-      mPinEntry.setText("");
-      mUiState.onEnter(this);
-    }
-    mUiState.onInputChanged(this);
-  }
-
-  /**
-   * Validates PIN and returns a message to display if PIN fails test.
-   *
-   * @param password the raw password the user typed in
-   * @return error message to show to user or null if password is OK
-   */
-  private CharSequence validatePassword(String password) {
-    if (mPinMinLength == 0 && mPinMaxLength == 0) {
-      // Invalid length requirement is sent by the server, just accept anything and let the
-      // server decide.
-      return null;
-    }
-
-    if (password.length() < mPinMinLength) {
-      return getString(R.string.vm_change_pin_error_too_short);
-    }
-    return null;
-  }
-
-  private void setHeader(int text) {
-    mHeaderText.setText(text);
-    mPinEntry.setContentDescription(mHeaderText.getText());
-  }
-
-  /**
-   * Get the corresponding message for the {@link ChangePinResult}.<code>result</code> must not
-   * {@link OmtpConstants#CHANGE_PIN_SUCCESS}
-   */
-  private CharSequence getChangePinResultMessage(@ChangePinResult int result) {
-    switch (result) {
-      case OmtpConstants.CHANGE_PIN_TOO_SHORT:
-        return getString(R.string.vm_change_pin_error_too_short);
-      case OmtpConstants.CHANGE_PIN_TOO_LONG:
-        return getString(R.string.vm_change_pin_error_too_long);
-      case OmtpConstants.CHANGE_PIN_TOO_WEAK:
-        return getString(R.string.vm_change_pin_error_too_weak);
-      case OmtpConstants.CHANGE_PIN_INVALID_CHARACTER:
-        return getString(R.string.vm_change_pin_error_invalid);
-      case OmtpConstants.CHANGE_PIN_MISMATCH:
-        return getString(R.string.vm_change_pin_error_mismatch);
-      case OmtpConstants.CHANGE_PIN_SYSTEM_ERROR:
-        return getString(R.string.vm_change_pin_error_system_error);
-      default:
-        VvmLog.wtf(TAG, "Unexpected ChangePinResult " + result);
-        return null;
-    }
-  }
-
-  private void verifyOldPin() {
-    processPinChange(mOldPin, mOldPin);
-  }
-
-  private void setNextEnabled(boolean enabled) {
-    mNextButton.setEnabled(enabled);
-  }
-
-  private void showError(CharSequence message) {
-    showError(message, null);
-  }
-
-  private void showError(CharSequence message, @Nullable OnDismissListener callback) {
-    new AlertDialog.Builder(this)
-        .setMessage(message)
-        .setPositiveButton(android.R.string.ok, null)
-        .setOnDismissListener(callback)
-        .show();
-  }
-
-  /** Asynchronous call to change the PIN on the server. */
-  private void processPinChange(String oldPin, String newPin) {
-    mProgressDialog = new ProgressDialog(this);
-    mProgressDialog.setCancelable(false);
-    mProgressDialog.setMessage(getString(R.string.vm_change_pin_progress_message));
-    mProgressDialog.show();
-
-    ChangePinNetworkRequestCallback callback = new ChangePinNetworkRequestCallback(oldPin, newPin);
-    callback.requestNetwork();
-  }
-
-  private class ChangePinNetworkRequestCallback extends VvmNetworkRequestCallback {
-
-    private final String mOldPin;
-    private final String mNewPin;
-
-    public ChangePinNetworkRequestCallback(String oldPin, String newPin) {
-      super(
-          mConfig, mPhoneAccountHandle, VoicemailChangePinActivity.this.getVoicemailStatusEditor());
-      mOldPin = oldPin;
-      mNewPin = newPin;
-    }
-
-    @Override
-    public void onAvailable(Network network) {
-      super.onAvailable(network);
-      try (ImapHelper helper =
-          new ImapHelper(
-              VoicemailChangePinActivity.this,
-              mPhoneAccountHandle,
-              network,
-              getVoicemailStatusEditor())) {
-
-        @ChangePinResult int result = helper.changePin(mOldPin, mNewPin);
-        sendResult(result);
-      } catch (InitializingException | MessagingException e) {
-        VvmLog.e(TAG, "ChangePinNetworkRequestCallback: onAvailable: ", e);
-        sendResult(OmtpConstants.CHANGE_PIN_SYSTEM_ERROR);
-      }
-    }
-
-    @Override
-    public void onFailed(String reason) {
-      super.onFailed(reason);
-      sendResult(OmtpConstants.CHANGE_PIN_SYSTEM_ERROR);
-    }
-
-    private void sendResult(@ChangePinResult int result) {
-      VvmLog.i(TAG, "Change PIN result: " + result);
-      if (mProgressDialog.isShowing()
-          && !VoicemailChangePinActivity.this.isDestroyed()
-          && !VoicemailChangePinActivity.this.isFinishing()) {
-        mProgressDialog.dismiss();
-      } else {
-        VvmLog.i(TAG, "Dialog not visible, not dismissing");
-      }
-      mHandler.obtainMessage(MESSAGE_HANDLE_RESULT, result, 0).sendToTarget();
-      releaseNetwork();
-    }
-  }
-}
diff --git a/java/com/android/voicemail/impl/settings/VoicemailRingtonePreference.java b/java/com/android/voicemail/impl/settings/VoicemailRingtonePreference.java
deleted file mode 100644
index 22c729c..0000000
--- a/java/com/android/voicemail/impl/settings/VoicemailRingtonePreference.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2017 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.voicemail.impl.settings;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.net.Uri;
-import android.os.Build.VERSION_CODES;
-import android.os.Handler;
-import android.os.Message;
-import android.preference.RingtonePreference;
-import android.telecom.PhoneAccountHandle;
-import android.telephony.TelephonyManager;
-import android.util.AttributeSet;
-import com.android.dialer.common.Assert;
-import com.android.dialer.util.SettingsUtil;
-
-/**
- * Looks up the voicemail ringtone's name asynchronously and updates the preference's summary when
- * it is created or updated.
- */
-@TargetApi(VERSION_CODES.O)
-public class VoicemailRingtonePreference extends RingtonePreference {
-
-  /** Callback when the ringtone name has been fetched. */
-  public interface VoicemailRingtoneNameChangeListener {
-    void onVoicemailRingtoneNameChanged(CharSequence name);
-  }
-
-  private static final int MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY = 1;
-
-  private PhoneAccountHandle phoneAccountHandle;
-  private final TelephonyManager telephonyManager;
-
-  private VoicemailRingtoneNameChangeListener mVoicemailRingtoneNameChangeListener;
-  private Runnable mVoicemailRingtoneLookupRunnable;
-  private final Handler mVoicemailRingtoneLookupComplete =
-      new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-          switch (msg.what) {
-            case MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY:
-              if (mVoicemailRingtoneNameChangeListener != null) {
-                mVoicemailRingtoneNameChangeListener.onVoicemailRingtoneNameChanged(
-                    (CharSequence) msg.obj);
-              }
-              setSummary((CharSequence) msg.obj);
-              break;
-            default:
-              Assert.fail();
-          }
-        }
-      };
-
-  public VoicemailRingtonePreference(Context context, AttributeSet attrs) {
-    super(context, attrs);
-    telephonyManager = context.getSystemService(TelephonyManager.class);
-  }
-
-  public void init(PhoneAccountHandle phoneAccountHandle, CharSequence oldRingtoneName) {
-    this.phoneAccountHandle = phoneAccountHandle;
-    setSummary(oldRingtoneName);
-    mVoicemailRingtoneLookupRunnable =
-        new Runnable() {
-          @Override
-          public void run() {
-            SettingsUtil.getRingtoneName(
-                getContext(),
-                mVoicemailRingtoneLookupComplete,
-                telephonyManager.getVoicemailRingtoneUri(phoneAccountHandle),
-                MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY);
-          }
-        };
-
-    updateRingtoneName();
-  }
-
-  public void setVoicemailRingtoneNameChangeListener(VoicemailRingtoneNameChangeListener l) {
-    mVoicemailRingtoneNameChangeListener = l;
-  }
-
-  @Override
-  protected Uri onRestoreRingtone() {
-    return telephonyManager.getVoicemailRingtoneUri(phoneAccountHandle);
-  }
-
-  @Override
-  protected void onSaveRingtone(Uri ringtoneUri) {
-    telephonyManager.setVoicemailRingtoneUri(phoneAccountHandle, ringtoneUri);
-    updateRingtoneName();
-  }
-
-  private void updateRingtoneName() {
-    new Thread(mVoicemailRingtoneLookupRunnable).start();
-  }
-}
diff --git a/java/com/android/voicemail/impl/settings/VoicemailSettingsFragment.java b/java/com/android/voicemail/impl/settings/VoicemailSettingsFragment.java
deleted file mode 100644
index 4652238..0000000
--- a/java/com/android/voicemail/impl/settings/VoicemailSettingsFragment.java
+++ /dev/null
@@ -1,282 +0,0 @@
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * <p>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
- *
- * <p>http://www.apache.org/licenses/LICENSE-2.0
- *
- * <p>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.voicemail.impl.settings;
-
-import android.annotation.TargetApi;
-import android.content.Intent;
-import android.os.Build.VERSION_CODES;
-import android.os.Bundle;
-import android.preference.Preference;
-import android.preference.Preference.OnPreferenceClickListener;
-import android.preference.PreferenceFragment;
-import android.preference.PreferenceScreen;
-import android.preference.SwitchPreference;
-import android.provider.Settings;
-import android.support.annotation.Nullable;
-import android.telecom.PhoneAccountHandle;
-import android.telephony.TelephonyManager;
-import com.android.dialer.common.Assert;
-import com.android.dialer.logging.DialerImpression;
-import com.android.dialer.logging.Logger;
-import com.android.dialer.notification.NotificationChannelManager;
-import com.android.voicemail.VoicemailClient;
-import com.android.voicemail.VoicemailComponent;
-import com.android.voicemail.impl.OmtpVvmCarrierConfigHelper;
-import com.android.voicemail.impl.R;
-import com.android.voicemail.impl.VvmLog;
-import com.android.voicemail.impl.sync.VvmAccountManager;
-
-/**
- * Fragment for voicemail settings. Requires {@link VoicemailClient#PARAM_PHONE_ACCOUNT_HANDLE} set
- * in arguments.
- */
-@TargetApi(VERSION_CODES.O)
-public class VoicemailSettingsFragment extends PreferenceFragment
-    implements Preference.OnPreferenceChangeListener, VvmAccountManager.Listener {
-
-  private static final String TAG = "VmSettingsActivity";
-
-  @Nullable private PhoneAccountHandle phoneAccountHandle;
-  private OmtpVvmCarrierConfigHelper omtpVvmCarrierConfigHelper;
-
-  private Preference voicemailNotificationPreference;
-  private SwitchPreference voicemailVisualVoicemail;
-  private SwitchPreference autoArchiveSwitchPreference;
-  private SwitchPreference donateVoicemailSwitchPreference;
-  private Preference voicemailChangePinPreference;
-  private PreferenceScreen advancedSettings;
-
-  @Override
-  public void onCreate(Bundle icicle) {
-    super.onCreate(icicle);
-
-    phoneAccountHandle =
-        Assert.isNotNull(getArguments().getParcelable(VoicemailClient.PARAM_PHONE_ACCOUNT_HANDLE));
-
-    omtpVvmCarrierConfigHelper = new OmtpVvmCarrierConfigHelper(getContext(), phoneAccountHandle);
-  }
-
-  @Override
-  public void onResume() {
-    super.onResume();
-    Logger.get(getContext()).logImpression(DialerImpression.Type.VVM_SETTINGS_VIEWED);
-    VvmAccountManager.addListener(this);
-    PreferenceScreen preferenceScreen = getPreferenceScreen();
-    if (preferenceScreen != null) {
-      preferenceScreen.removeAll();
-    }
-
-    addPreferencesFromResource(R.xml.voicemail_settings);
-
-    PreferenceScreen prefSet = getPreferenceScreen();
-
-    voicemailNotificationPreference =
-        findPreference(getString(R.string.voicemail_notifications_key));
-    voicemailNotificationPreference.setIntent(getNotificationSettingsIntent());
-
-    voicemailNotificationPreference.setOnPreferenceClickListener(
-        new OnPreferenceClickListener() {
-          @Override
-          public boolean onPreferenceClick(Preference preference) {
-            Logger.get(getContext())
-                .logImpression(DialerImpression.Type.VVM_CHANGE_RINGTONE_CLICKED);
-            // Let the preference handle the click.
-            return false;
-          }
-        });
-
-    voicemailVisualVoicemail =
-        (SwitchPreference) findPreference(getString(R.string.voicemail_visual_voicemail_key));
-
-    autoArchiveSwitchPreference =
-        (SwitchPreference)
-            findPreference(getString(R.string.voicemail_visual_voicemail_archive_key));
-
-    donateVoicemailSwitchPreference =
-        (SwitchPreference)
-            findPreference(getString(R.string.voicemail_visual_voicemail_donation_key));
-
-    if (!VoicemailComponent.get(getContext())
-        .getVoicemailClient()
-        .isVoicemailArchiveAvailable(getContext())) {
-      getPreferenceScreen().removePreference(autoArchiveSwitchPreference);
-    }
-
-    if (!VoicemailComponent.get(getContext())
-        .getVoicemailClient()
-        .isVoicemailDonationEnabled(getContext(), phoneAccountHandle)) {
-      getPreferenceScreen().removePreference(donateVoicemailSwitchPreference);
-    }
-
-    voicemailChangePinPreference = findPreference(getString(R.string.voicemail_change_pin_key));
-
-    if (omtpVvmCarrierConfigHelper.isValid()) {
-      Assert.isNotNull(phoneAccountHandle);
-      Intent changePinIntent =
-          new Intent(new Intent(getContext(), VoicemailChangePinActivity.class));
-      changePinIntent.putExtra(
-          VoicemailChangePinActivity.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
-
-      voicemailChangePinPreference.setIntent(changePinIntent);
-      voicemailChangePinPreference.setOnPreferenceClickListener(
-          new OnPreferenceClickListener() {
-            @Override
-            public boolean onPreferenceClick(Preference preference) {
-              Logger.get(getContext()).logImpression(DialerImpression.Type.VVM_CHANGE_PIN_CLICKED);
-              // Let the preference handle the click.
-              return false;
-            }
-          });
-      if (VoicemailChangePinActivity.isDefaultOldPinSet(getContext(), phoneAccountHandle)) {
-        voicemailChangePinPreference.setTitle(R.string.voicemail_set_pin_preference_title);
-      } else {
-        voicemailChangePinPreference.setTitle(R.string.voicemail_change_pin_preference_title);
-      }
-      updateChangePin();
-
-      voicemailVisualVoicemail.setOnPreferenceChangeListener(this);
-      voicemailVisualVoicemail.setChecked(
-          VisualVoicemailSettingsUtil.isEnabled(getContext(), phoneAccountHandle));
-
-      autoArchiveSwitchPreference.setOnPreferenceChangeListener(this);
-      autoArchiveSwitchPreference.setChecked(
-          VisualVoicemailSettingsUtil.isArchiveEnabled(getContext(), phoneAccountHandle));
-
-      donateVoicemailSwitchPreference.setOnPreferenceChangeListener(this);
-      donateVoicemailSwitchPreference.setChecked(
-          VisualVoicemailSettingsUtil.isVoicemailDonationEnabled(getContext(), phoneAccountHandle));
-      updateDonateVoicemail();
-    } else {
-      prefSet.removePreference(voicemailVisualVoicemail);
-      prefSet.removePreference(autoArchiveSwitchPreference);
-      prefSet.removePreference(donateVoicemailSwitchPreference);
-      prefSet.removePreference(voicemailChangePinPreference);
-    }
-
-    advancedSettings =
-        (PreferenceScreen) findPreference(getString(R.string.voicemail_advanced_settings_key));
-    Intent advancedSettingsIntent = new Intent(TelephonyManager.ACTION_CONFIGURE_VOICEMAIL);
-    advancedSettingsIntent.putExtra(TelephonyManager.EXTRA_HIDE_PUBLIC_SETTINGS, true);
-    advancedSettingsIntent.putExtra(
-        TelephonyManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
-    advancedSettings.setIntent(advancedSettingsIntent);
-    voicemailChangePinPreference.setOnPreferenceClickListener(
-        new OnPreferenceClickListener() {
-          @Override
-          public boolean onPreferenceClick(Preference preference) {
-            Logger.get(getContext())
-                .logImpression(DialerImpression.Type.VVM_ADVANCED_SETINGS_CLICKED);
-            // Let the preference handle the click.
-            return false;
-          }
-        });
-  }
-
-  @Override
-  public void onPause() {
-    VvmAccountManager.removeListener(this);
-    super.onPause();
-  }
-
-  /**
-   * Implemented to support onPreferenceChangeListener to look for preference changes.
-   *
-   * @param preference is the preference to be changed
-   * @param objValue should be the value of the selection, NOT its localized display value.
-   */
-  @Override
-  public boolean onPreferenceChange(Preference preference, Object objValue) {
-    VvmLog.d(TAG, "onPreferenceChange: \"" + preference + "\" changed to \"" + objValue + "\"");
-    if (preference.getKey().equals(voicemailVisualVoicemail.getKey())) {
-      boolean isEnabled = (boolean) objValue;
-      VisualVoicemailSettingsUtil.setEnabled(getContext(), phoneAccountHandle, isEnabled);
-
-      if (isEnabled) {
-        Logger.get(getContext()).logImpression(DialerImpression.Type.VVM_USER_ENABLED_IN_SETTINGS);
-      } else {
-        Logger.get(getContext()).logImpression(DialerImpression.Type.VVM_USER_DISABLED_IN_SETTINGS);
-      }
-
-      updateChangePin();
-      updateDonateVoicemail();
-    } else if (preference.getKey().equals(autoArchiveSwitchPreference.getKey())) {
-      logArchiveToggle((boolean) objValue);
-      VisualVoicemailSettingsUtil.setArchiveEnabled(
-          getContext(), phoneAccountHandle, (boolean) objValue);
-    } else if (preference.getKey().equals(donateVoicemailSwitchPreference.getKey())) {
-      logArchiveToggle((boolean) objValue);
-      VisualVoicemailSettingsUtil.setVoicemailDonationEnabled(
-          getContext(), phoneAccountHandle, (boolean) objValue);
-    }
-
-    // Always let the preference setting proceed.
-    return true;
-  }
-
-  private void updateChangePin() {
-    if (!VisualVoicemailSettingsUtil.isEnabled(getContext(), phoneAccountHandle)) {
-      voicemailChangePinPreference.setSummary(
-          R.string.voicemail_change_pin_preference_summary_disable);
-      voicemailChangePinPreference.setEnabled(false);
-    } else if (!VvmAccountManager.isAccountActivated(getContext(), phoneAccountHandle)) {
-      voicemailChangePinPreference.setSummary(
-          R.string.voicemail_change_pin_preference_summary_not_activated);
-      voicemailChangePinPreference.setEnabled(false);
-    } else {
-      voicemailChangePinPreference.setSummary(null);
-      voicemailChangePinPreference.setEnabled(true);
-    }
-  }
-
-  private void updateDonateVoicemail() {
-    if (!VisualVoicemailSettingsUtil.isEnabled(getContext(), phoneAccountHandle)) {
-      donateVoicemailSwitchPreference.setSummary(
-          R.string.voicemail_donate_preference_summary_disable);
-      donateVoicemailSwitchPreference.setEnabled(false);
-    } else if (!VvmAccountManager.isAccountActivated(getContext(), phoneAccountHandle)) {
-      donateVoicemailSwitchPreference.setSummary(
-          R.string.voicemail_donate_preference_summary_not_activated);
-      donateVoicemailSwitchPreference.setEnabled(false);
-    } else {
-      donateVoicemailSwitchPreference.setSummary(R.string.voicemail_donate_preference_summary_info);
-      donateVoicemailSwitchPreference.setEnabled(true);
-    }
-  }
-
-  private void logArchiveToggle(boolean userTurnedOn) {
-    if (userTurnedOn) {
-      Logger.get(getContext())
-          .logImpression(DialerImpression.Type.VVM_USER_TURNED_ARCHIVE_ON_FROM_SETTINGS);
-    } else {
-      Logger.get(getContext())
-          .logImpression(DialerImpression.Type.VVM_USER_TURNED_ARCHIVE_OFF_FROM_SETTINGS);
-    }
-  }
-
-  @Override
-  public void onActivationStateChanged(PhoneAccountHandle phoneAccountHandle, boolean isActivated) {
-    if (this.phoneAccountHandle.equals(phoneAccountHandle)) {
-      updateChangePin();
-      updateDonateVoicemail();
-    }
-  }
-
-  private Intent getNotificationSettingsIntent() {
-    String channelId =
-        NotificationChannelManager.getVoicemailChannelId(getContext(), phoneAccountHandle);
-    return new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
-        .putExtra(Settings.EXTRA_CHANNEL_ID, channelId)
-        .putExtra(Settings.EXTRA_APP_PACKAGE, getContext().getPackageName());
-  }
-}
diff --git a/java/com/android/voicemail/impl/sync/VvmAccountManager.java b/java/com/android/voicemail/impl/sync/VvmAccountManager.java
index f458b2a..e7f2eef 100644
--- a/java/com/android/voicemail/impl/sync/VvmAccountManager.java
+++ b/java/com/android/voicemail/impl/sync/VvmAccountManager.java
@@ -29,6 +29,7 @@
 import com.android.dialer.common.PerAccountSharedPreferences;
 import com.android.dialer.common.concurrent.ThreadUtil;
 import com.android.dialer.storage.StorageComponent;
+import com.android.voicemail.VoicemailClient.ActivationStateListener;
 import com.android.voicemail.impl.OmtpConstants;
 import com.android.voicemail.impl.VisualVoicemailPreferences;
 import com.android.voicemail.impl.VoicemailStatus;
@@ -50,15 +51,9 @@
 public class VvmAccountManager {
   public static final String TAG = "VvmAccountManager";
 
-  /** Listener for activation state changes. Will be called on the main thread. */
-  public interface Listener {
-    @MainThread
-    void onActivationStateChanged(PhoneAccountHandle phoneAccountHandle, boolean isActivated);
-  }
-
   @VisibleForTesting static final String IS_ACCOUNT_ACTIVATED = "is_account_activated";
 
-  private static Set<Listener> listeners = new ArraySet<>();
+  private static final Set<ActivationStateListener> listeners = new ArraySet<>();
 
   public static void addAccount(
       Context context, PhoneAccountHandle phoneAccountHandle, StatusMessage statusMessage) {
@@ -69,7 +64,7 @@
 
     ThreadUtil.postOnUiThread(
         () -> {
-          for (Listener listener : listeners) {
+          for (ActivationStateListener listener : listeners) {
             listener.onActivationStateChanged(phoneAccountHandle, true);
           }
         });
@@ -86,7 +81,7 @@
         .apply();
     ThreadUtil.postOnUiThread(
         () -> {
-          for (Listener listener : listeners) {
+          for (ActivationStateListener listener : listeners) {
             listener.onActivationStateChanged(phoneAccount, false);
           }
         });
@@ -113,13 +108,13 @@
   }
 
   @MainThread
-  public static void addListener(Listener listener) {
+  public static void addListener(ActivationStateListener listener) {
     Assert.isMainThread();
     listeners.add(listener);
   }
 
   @MainThread
-  public static void removeListener(Listener listener) {
+  public static void removeListener(ActivationStateListener listener) {
     Assert.isMainThread();
     listeners.remove(listener);
   }
diff --git a/java/com/android/voicemail/stub/StubVoicemailClient.java b/java/com/android/voicemail/stub/StubVoicemailClient.java
index 4b8ed9a..0fe533e 100644
--- a/java/com/android/voicemail/stub/StubVoicemailClient.java
+++ b/java/com/android/voicemail/stub/StubVoicemailClient.java
@@ -17,12 +17,12 @@
 package com.android.voicemail.stub;
 
 import android.content.Context;
-import android.content.Intent;
 import android.os.PersistableBundle;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.telecom.PhoneAccountHandle;
-import android.telephony.TelephonyManager;
+import com.android.dialer.common.Assert;
+import com.android.voicemail.PinChanger;
 import com.android.voicemail.VoicemailClient;
 import java.util.List;
 import javax.inject.Inject;
@@ -57,11 +57,6 @@
       Context context, StringBuilder where, List<String> selectionArgs) {}
 
   @Override
-  public String getSettingsFragment() {
-    return null;
-  }
-
-  @Override
   public boolean isVoicemailArchiveEnabled(Context context, PhoneAccountHandle phoneAccountHandle) {
     return false;
   }
@@ -86,11 +81,8 @@
   }
 
   @Override
-  public Intent getSetPinIntent(Context context, PhoneAccountHandle phoneAccountHandle) {
-    Intent intent = new Intent(TelephonyManager.ACTION_CONFIGURE_VOICEMAIL);
-    intent.putExtra(TelephonyManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
-    return intent;
-  }
+  public void setVoicemailDonationEnabled(
+      Context context, PhoneAccountHandle phoneAccountHandle, boolean enabled) {}
 
   @Override
   public boolean isActivated(Context context, PhoneAccountHandle phoneAccountHandle) {
@@ -113,5 +105,25 @@
   public void onShutdown(@NonNull Context context) {}
 
   @Override
+  public void addActivationStateListener(ActivationStateListener listener) {
+    throw Assert.createAssertionFailException("should never be called on stub.");
+  }
+
+  @Override
+  public void removeActivationStateListener(ActivationStateListener listener) {
+    throw Assert.createAssertionFailException("should never be called on stub.");
+  }
+
+  @Override
+  public boolean hasCarrierSupport(Context context, PhoneAccountHandle phoneAccountHandle) {
+    return false;
+  }
+
+  @Override
+  public PinChanger createPinChanger(Context context, PhoneAccountHandle phoneAccountHandle) {
+    throw Assert.createAssertionFailException("should never be called on stub.");
+  }
+
+  @Override
   public void onTosAccepted(Context context) {}
 }