Merge "Remove vvm dependence on AccountManager, save values in shared prefs." into mnc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f663328..9e54312 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -634,15 +634,6 @@
                 <data android:scheme="sms" />
             </intent-filter>
         </receiver>
-        <service
-            android:name="android.telecom.AuthenticatorService">
-            <intent-filter>
-                <action android:name="android.accounts.AccountAuthenticator"/>
-            </intent-filter>
-            <meta-data
-                android:name="android.accounts.AccountAuthenticator"
-                android:resource="@xml/authenticator" />
-       </service>
        <receiver android:name="com.android.phone.vvm.omtp.SimChangeReceiver"
             android:exported="true">
             <intent-filter>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8565af8..9b3dee9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1212,7 +1212,7 @@
     -->
     <string name="description_dial_button">dial</string>
 
-    <!-- Dialog title for the vibration settings for voicemail notifications [CHAR LIMIT=40] -->
+    <!-- Title for the vibration settings for voicemail notifications [CHAR LIMIT=40] -->
     <string name="voicemail_notification_vibrate_when_title" msgid="8731372580674292759">Vibrate</string>
     <!-- Dialog title for the vibration settings for voice mail notifications [CHAR LIMIT=40]-->
     <string name="voicemail_notification_vibarte_when_dialog_title" msgid="8995274609647451109">Vibrate</string>
diff --git a/res/xml/authenticator.xml b/res/xml/authenticator.xml
deleted file mode 100644
index f035d3a..0000000
--- a/res/xml/authenticator.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 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.
--->
-<account-authenticator
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:accountType="com.android.phone.vvm.omtp" />
\ No newline at end of file
diff --git a/src/com/android/phone/settings/VisualVoicemailSettingsUtil.java b/src/com/android/phone/settings/VisualVoicemailSettingsUtil.java
new file mode 100644
index 0000000..e3a9307
--- /dev/null
+++ b/src/com/android/phone/settings/VisualVoicemailSettingsUtil.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2015 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.phone.settings;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.telecom.PhoneAccountHandle;
+
+import com.android.phone.vvm.omtp.OmtpConstants;
+import com.android.phone.vvm.omtp.sms.StatusMessage;
+
+/**
+ * Save visual voicemail login values in shared preferences to be retrieved later.
+ */
+public class VisualVoicemailSettingsUtil {
+    private static final String VISUAL_VOICEMAIL_SHARED_PREFS_KEY_PREFIX =
+            "visual_voicemail_";
+
+    private static final String IS_ENABLED_KEY = "is_enabled";
+
+    public static void setVisualVoicemailEnabled(Context context, PhoneAccountHandle phoneAccount,
+            boolean isEnabled) {
+        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+        SharedPreferences.Editor editor = prefs.edit();
+        editor.putBoolean(
+                getVisualVoicemailSharedPrefsKey(IS_ENABLED_KEY, phoneAccount), isEnabled);
+        editor.commit();
+    }
+
+    public static boolean getVisualVoicemailEnabled(Context context,
+            PhoneAccountHandle phoneAccount) {
+        if (phoneAccount == null) {
+            return false;
+        }
+        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+        return prefs.getBoolean(getVisualVoicemailSharedPrefsKey(IS_ENABLED_KEY, phoneAccount),
+                true);
+    }
+
+    public static void setSourceCredentialsFromStatusMessage(Context context,
+            PhoneAccountHandle phoneAccount, StatusMessage message) {
+        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+        SharedPreferences.Editor editor = prefs.edit();
+
+        editor.putString(
+                getVisualVoicemailSharedPrefsKey(OmtpConstants.IMAP_PORT, phoneAccount),
+                message.getImapPort());
+        editor.putString(
+                getVisualVoicemailSharedPrefsKey(OmtpConstants.SERVER_ADDRESS, phoneAccount),
+                message.getServerAddress());
+        editor.putString(
+                getVisualVoicemailSharedPrefsKey(OmtpConstants.IMAP_USER_NAME, phoneAccount),
+                message.getImapUserName());
+        editor.putString(
+                getVisualVoicemailSharedPrefsKey(OmtpConstants.IMAP_PASSWORD, phoneAccount),
+                message.getImapPassword());
+        editor.commit();
+    }
+
+    public static String getCredentialForSource(Context context, String key,
+            PhoneAccountHandle phoneAccount) {
+        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+        return prefs.getString(getVisualVoicemailSharedPrefsKey(key, phoneAccount), null);
+    }
+
+    private static String getVisualVoicemailSharedPrefsKey(String key,
+            PhoneAccountHandle phoneAccount) {
+        return VISUAL_VOICEMAIL_SHARED_PREFS_KEY_PREFIX + key + "_" + phoneAccount.getId();
+    }
+}
diff --git a/src/com/android/phone/vvm/omtp/OmtpVvmCarrierConfigHelper.java b/src/com/android/phone/vvm/omtp/OmtpVvmCarrierConfigHelper.java
new file mode 100644
index 0000000..f2df9b1
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/OmtpVvmCarrierConfigHelper.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2015 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.phone.vvm.omtp;
+
+import android.content.Context;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SmsManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.phone.vvm.omtp.sms.OmtpCvvmMessageSender;
+import com.android.phone.vvm.omtp.sms.OmtpMessageSender;
+import com.android.phone.vvm.omtp.sms.OmtpStandardMessageSender;
+
+/**
+ * Handle activation and deactivation of a visual voicemail source. This class is necessary to
+ * retrieve carrier vvm configuration details before sending the appropriate texts.
+ */
+public class OmtpVvmCarrierConfigHelper {
+    private static final String TAG = "OmtpVvmCarrierConfigHelper";
+
+    public static void startActivation(Context context, int subId) {
+        OmtpMessageSender messageSender = getMessageSender(context, subId);
+        if (messageSender != null) {
+            Log.i(TAG, "Requesting VVM activation for subId: " + subId);
+            messageSender.requestVvmActivation(null);
+        }
+    }
+
+    public static void startDeactivation(Context context, int subId) {
+        OmtpMessageSender messageSender = getMessageSender(context, subId);
+        if (messageSender != null) {
+            Log.i(TAG, "Requesting VVM deactivation for subId: " + subId);
+            messageSender.requestVvmDeactivation(null);
+        }
+    }
+
+    private static OmtpMessageSender getMessageSender(Context context, int subId) {
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            Log.w(TAG, "Invalid subscriptionId or subscriptionId not provided in intent.");
+            return null;
+        }
+
+        CarrierConfigManager carrierConfigManager = (CarrierConfigManager)
+                context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+        if (carrierConfigManager == null) {
+            Log.w(TAG, "No carrier config service found.");
+            return null;
+        }
+
+        PersistableBundle carrierConfig = carrierConfigManager.getConfigForSubId(subId);
+        if (carrierConfig == null) {
+            Log.w(TAG, "Empty carrier config.");
+            return null;
+        }
+
+        String vvmType = carrierConfig.getString(
+                CarrierConfigManager.STRING_VVM_TYPE, null);
+
+        if (!(TelephonyManager.VVM_TYPE_OMTP.equals(vvmType) ||
+                TelephonyManager.VVM_TYPE_CVVM.equals(vvmType))) {
+            // This is not an OMTP visual voicemail compatible carrier.
+            return null;
+        }
+
+        int applicationPort = carrierConfig.getInt(
+                CarrierConfigManager.INT_VVM_PORT_NUMBER, 0);
+        String destinationNumber = carrierConfig.getString(
+                CarrierConfigManager.STRING_VVM_DESTINATION_NUMBER);
+        if (TextUtils.isEmpty(destinationNumber)) {
+            Log.w(TAG, "No destination number for this carrier.");
+            return null;
+        }
+
+        OmtpMessageSender messageSender = null;
+        SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(subId);
+        switch (vvmType) {
+            case TelephonyManager.VVM_TYPE_OMTP:
+                messageSender = new OmtpStandardMessageSender(smsManager, (short) applicationPort,
+                        destinationNumber, null, OmtpConstants.PROTOCOL_VERSION1_1, null);
+                break;
+            case TelephonyManager.VVM_TYPE_CVVM:
+                messageSender = new OmtpCvvmMessageSender(smsManager, (short) applicationPort,
+                        destinationNumber);
+                break;
+            default:
+                Log.w(TAG, "Unexpected visual voicemail type: "+vvmType);
+        }
+
+        return messageSender;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/phone/vvm/omtp/SimChangeReceiver.java b/src/com/android/phone/vvm/omtp/SimChangeReceiver.java
index cd7a694..5284f0c 100644
--- a/src/com/android/phone/vvm/omtp/SimChangeReceiver.java
+++ b/src/com/android/phone/vvm/omtp/SimChangeReceiver.java
@@ -18,21 +18,14 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
-import android.telephony.SmsManager;
 import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyIntents;
-import com.android.phone.vvm.omtp.sms.OmtpMessageSender;
-import com.android.phone.vvm.omtp.sms.OmtpStandardMessageSender;
-import com.android.phone.vvm.omtp.sms.OmtpCvvmMessageSender;
-import com.android.phone.vvm.omtp.sync.OmtpVvmSyncAccountManager;
+import com.android.phone.vvm.omtp.sync.OmtpVvmSourceManager;
 
 /**
  * This class listens to the {@link CarrierConfigManager#ACTION_CARRIER_CONFIG_CHANGED} and
@@ -44,8 +37,6 @@
  */
 public class SimChangeReceiver extends BroadcastReceiver {
     private final String TAG = "SimChangeReceiver";
-    // Whether CVVM is allowed, is currently false until settings to enable/disable vvm are added.
-    private boolean CVVM_ALLOWED = false;
 
     @Override
     public void onReceive(Context context, Intent intent) {
@@ -60,76 +51,14 @@
                 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(
                         intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE))) {
                     Log.i(TAG, "Sim removed, removing inactive accounts");
-                    OmtpVvmSyncAccountManager.getInstance(context).removeInactiveAccounts();
+                    OmtpVvmSourceManager.getInstance(context).removeInactiveSources();
                 }
                 break;
             case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
-                handleCarrierConfigChange(context, intent);
+                int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+                        SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+                OmtpVvmCarrierConfigHelper.startActivation(context, subId);
                 break;
         }
     }
-
-    private void handleCarrierConfigChange(Context context, Intent intent) {
-        int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
-                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
-        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
-            Log.w(TAG, "Invalid subscriptionId or subscriptionId not provided in intent.");
-            return;
-        }
-
-        CarrierConfigManager carrierConfigManager = (CarrierConfigManager)
-                context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
-        if (carrierConfigManager == null) {
-            Log.w(TAG, "No carrier config service found.");
-            return;
-        }
-
-        PersistableBundle carrierConfig = carrierConfigManager.getConfigForSubId(subId);
-        if (carrierConfig == null) {
-            Log.w(TAG, "Empty carrier config.");
-            return;
-        }
-        String vvmType = carrierConfig.getString(
-                CarrierConfigManager.STRING_VVM_TYPE, null);
-
-        if (!(TelephonyManager.VVM_TYPE_OMTP.equals(vvmType) ||
-                TelephonyManager.VVM_TYPE_CVVM.equals(vvmType))) {
-            // This is not an OMTP visual voicemail compatible carrier.
-            return;
-        }
-
-        int applicationPort = carrierConfig.getInt(
-                CarrierConfigManager.INT_VVM_PORT_NUMBER, 0);
-        String destinationNumber = carrierConfig.getString(
-                CarrierConfigManager.STRING_VVM_DESTINATION_NUMBER);
-        if (TextUtils.isEmpty(destinationNumber)) {
-            Log.w(TAG, "No destination number for this carrier.");
-            return;
-        }
-
-        Log.i(TAG, "Requesting VVM activation for subId: " + subId);
-
-        OmtpMessageSender messageSender = null;
-        SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(subId);
-        switch (vvmType) {
-            case TelephonyManager.VVM_TYPE_OMTP:
-                messageSender = new OmtpStandardMessageSender(smsManager, (short) applicationPort,
-                        destinationNumber, null, OmtpConstants.PROTOCOL_VERSION1_1, null);
-                break;
-            case TelephonyManager.VVM_TYPE_CVVM:
-                if (CVVM_ALLOWED) {
-                    messageSender = new OmtpCvvmMessageSender(smsManager, (short) applicationPort,
-                            destinationNumber);
-                }
-                break;
-            default:
-                Log.w(TAG, "Unexpected visual voicemail type: "+vvmType);
-        }
-
-        // It should be impossible for the messageSender to be null because the two types of vvm
-        // were checked earlier.
-        if (messageSender != null) {
-            messageSender.requestVvmActivation(null);
-        }
-    }
 }
\ No newline at end of file
diff --git a/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java b/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
index 0110d65..de2ccf5 100644
--- a/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
+++ b/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
@@ -15,7 +15,6 @@
  */
 package com.android.phone.vvm.omtp.fetch;
 
-import android.accounts.Account;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -28,13 +27,14 @@
 import android.net.Uri;
 import android.provider.VoicemailContract;
 import android.provider.VoicemailContract.Voicemails;
+import android.telecom.PhoneAccountHandle;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.phone.PhoneUtils;
 import com.android.phone.vvm.omtp.imap.ImapHelper;
-import com.android.phone.vvm.omtp.sync.OmtpVvmSyncAccountManager;
+import com.android.phone.vvm.omtp.sync.OmtpVvmSourceManager;
 
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
@@ -58,9 +58,9 @@
     private NetworkRequest mNetworkRequest;
     private OmtpVvmNetworkRequestCallback mNetworkCallback;
     private Context mContext;
-    private Account mAccount;
     private String mUid;
     private ConnectivityManager mConnectivityManager;
+    private PhoneAccountHandle mPhoneAccount;
 
     @Override
     public void onReceive(final Context context, Intent intent) {
@@ -98,17 +98,15 @@
                             return;
                         }
                     }
-                    mAccount = new Account(accountId,
-                            OmtpVvmSyncAccountManager.ACCOUNT_TYPE);
 
-                    if (!OmtpVvmSyncAccountManager.getInstance(context)
-                            .isAccountRegistered(mAccount)) {
+                    mPhoneAccount = PhoneUtils.makePstnPhoneAccountHandle(accountId);
+                    if (!OmtpVvmSourceManager.getInstance(context)
+                            .isVvmSourceRegistered(mPhoneAccount)) {
                         Log.w(TAG, "Account not registered - cannot retrieve message.");
                         return;
                     }
 
-                    int subId = PhoneUtils.getSubIdForPhoneAccountHandle(
-                            PhoneUtils.makePstnPhoneAccountHandle(accountId));
+                    int subId = PhoneUtils.getSubIdForPhoneAccountHandle(mPhoneAccount);
 
                     mNetworkRequest = new NetworkRequest.Builder()
                             .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
@@ -132,7 +130,7 @@
             executor.execute(new Runnable() {
                 @Override
                 public void run() {
-                    new ImapHelper(mContext, mAccount, network).fetchVoicemailPayload(
+                    new ImapHelper(mContext, mPhoneAccount, network).fetchVoicemailPayload(
                             new VoicemailFetchedCallback(mContext, mUri), mUid);
                     releaseNetwork();
                 }
diff --git a/src/com/android/phone/vvm/omtp/imap/ImapHelper.java b/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
index 0d02700..3a197fc 100644
--- a/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
+++ b/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
@@ -15,8 +15,6 @@
  */
 package com.android.phone.vvm.omtp.imap;
 
-import android.accounts.Account;
-import android.accounts.AccountManager;
 import android.content.Context;
 import android.net.Network;
 import android.telecom.PhoneAccountHandle;
@@ -24,7 +22,6 @@
 
 import android.util.Base64;
 
-import com.android.phone.PhoneUtils;
 import com.android.phone.common.mail.Address;
 import com.android.phone.common.mail.Body;
 import com.android.phone.common.mail.BodyPart;
@@ -39,6 +36,7 @@
 import com.android.phone.common.mail.store.ImapStore;
 import com.android.phone.common.mail.store.imap.ImapConstants;
 import com.android.phone.common.mail.utils.LogUtils;
+import com.android.phone.settings.VisualVoicemailSettingsUtil;
 import com.android.phone.vvm.omtp.OmtpConstants;
 import com.android.phone.vvm.omtp.fetch.VoicemailFetchedCallback;
 
@@ -62,18 +60,21 @@
     private Context mContext;
     private PhoneAccountHandle mPhoneAccount;
 
-    public ImapHelper(Context context, Account account, Network network) {
+    public ImapHelper(Context context, PhoneAccountHandle phoneAccount, Network network) {
         try {
             mContext = context;
-            mPhoneAccount = PhoneUtils.makePstnPhoneAccountHandle(account.name);
+            mPhoneAccount = phoneAccount;
             TempDirectory.setTempDirectory(context);
 
-            AccountManager accountManager = AccountManager.get(context);
-            String username = accountManager.getUserData(account, OmtpConstants.IMAP_USER_NAME);
-            String password = accountManager.getUserData(account, OmtpConstants.IMAP_PASSWORD);
-            String serverName = accountManager.getUserData(account, OmtpConstants.SERVER_ADDRESS);
+            String username = VisualVoicemailSettingsUtil.getCredentialForSource(context,
+                    OmtpConstants.IMAP_USER_NAME, phoneAccount);
+            String password = VisualVoicemailSettingsUtil.getCredentialForSource(context,
+                    OmtpConstants.IMAP_PASSWORD, phoneAccount);
+            String serverName = VisualVoicemailSettingsUtil.getCredentialForSource(context,
+                    OmtpConstants.SERVER_ADDRESS, phoneAccount);
             int port = Integer.parseInt(
-                    accountManager.getUserData(account, OmtpConstants.IMAP_PORT));
+                    VisualVoicemailSettingsUtil.getCredentialForSource(context,
+                            OmtpConstants.IMAP_PORT, phoneAccount));
             // TODO: determine the security protocol (e.g. ssl, tls, none, etc.)
             mImapStore = new ImapStore(
                     context, username, password, port, serverName, ImapStore.FLAG_NONE, network);
diff --git a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
index 222ea26..1911f2a 100644
--- a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
+++ b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
@@ -15,7 +15,6 @@
  */
 package com.android.phone.vvm.omtp.sms;
 
-import android.accounts.Account;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -28,8 +27,9 @@
 
 import com.android.internal.telephony.PhoneConstants;
 import com.android.phone.PhoneUtils;
+import com.android.phone.settings.VisualVoicemailSettingsUtil;
 import com.android.phone.vvm.omtp.OmtpConstants;
-import com.android.phone.vvm.omtp.sync.OmtpVvmSyncAccountManager;
+import com.android.phone.vvm.omtp.sync.OmtpVvmSourceManager;
 import com.android.phone.vvm.omtp.sync.OmtpVvmSyncService;
 import com.android.phone.vvm.omtp.sync.VoicemailsQueryHelper;
 
@@ -48,6 +48,11 @@
         mPhoneAccount = PhoneUtils.makePstnPhoneAccountHandle(
                 intent.getExtras().getInt(PhoneConstants.PHONE_KEY));
 
+        if (!VisualVoicemailSettingsUtil.getVisualVoicemailEnabled(mContext, mPhoneAccount)) {
+            Log.v(TAG, "Received vvm message for disabled vvm source.");
+            return;
+        }
+
         SmsMessage[] messages = Telephony.Sms.Intents.getMessagesFromIntent(intent);
         StringBuilder messageBody = new StringBuilder();
 
@@ -94,11 +99,9 @@
                 queryHelper.insertIfUnique(voicemail);
                 break;
             case OmtpConstants.MAILBOX_UPDATE:
-                Account account = new Account(
-                        mPhoneAccount.getId(), OmtpVvmSyncAccountManager.ACCOUNT_TYPE);
                 Intent serviceIntent = new Intent(mContext, OmtpVvmSyncService.class);
                 serviceIntent.setAction(OmtpVvmSyncService.SYNC_DOWNLOAD_ONLY);
-                serviceIntent.putExtra(OmtpVvmSyncService.EXTRA_ACCOUNT, account);
+                serviceIntent.putExtra(OmtpVvmSyncService.EXTRA_PHONE_ACCOUNT, mPhoneAccount);
                 mContext.startService(serviceIntent);
                 break;
             case OmtpConstants.GREETINGS_UPDATE:
@@ -111,31 +114,26 @@
     }
 
     private void updateAccount(StatusMessage message) {
-        OmtpVvmSyncAccountManager vvmAccountSyncManager =
-                OmtpVvmSyncAccountManager.getInstance(mContext);
-        Account account = new Account(mPhoneAccount.getId(),
-                OmtpVvmSyncAccountManager.ACCOUNT_TYPE);
-
-        if (!vvmAccountSyncManager.isAccountRegistered(account)) {
-            // If the account has not been previously registered, it means that this STATUS sms
-            // is a result of the ACTIVATE sms, so register the voicemail source.
-            vvmAccountSyncManager.createSyncAccount(account);
-            VoicemailContract.Status.setStatus(mContext, mPhoneAccount,
-                    VoicemailContract.Status.CONFIGURATION_STATE_OK,
-                    VoicemailContract.Status.DATA_CHANNEL_STATE_OK,
-                    VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_OK);
-        }
+        OmtpVvmSourceManager vvmSourceManager =
+                OmtpVvmSourceManager.getInstance(mContext);
+        VoicemailContract.Status.setStatus(mContext, mPhoneAccount,
+                VoicemailContract.Status.CONFIGURATION_STATE_OK,
+                VoicemailContract.Status.DATA_CHANNEL_STATE_OK,
+                VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_OK);
 
         // Save the IMAP credentials in the corresponding account object so they are
         // persistent and can be retrieved.
-        vvmAccountSyncManager.setAccountCredentialsFromStatusMessage(account, message);
+        VisualVoicemailSettingsUtil.setSourceCredentialsFromStatusMessage(
+                mContext,
+                mPhoneAccount,
+                message);
 
         // Add a phone state listener so that changes to the communication channels can be recorded.
-        vvmAccountSyncManager.addPhoneStateListener(account);
+        vvmSourceManager.addPhoneStateListener(mPhoneAccount);
 
         Intent serviceIntent = new Intent(mContext, OmtpVvmSyncService.class);
         serviceIntent.setAction(OmtpVvmSyncService.SYNC_FULL_SYNC);
-        serviceIntent.putExtra(OmtpVvmSyncService.EXTRA_ACCOUNT, account);
+        serviceIntent.putExtra(OmtpVvmSyncService.EXTRA_PHONE_ACCOUNT, mPhoneAccount);
         mContext.startService(serviceIntent);
     }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSourceManager.java b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSourceManager.java
new file mode 100644
index 0000000..9f49c2a
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSourceManager.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2015 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.phone.vvm.omtp.sync;
+
+import android.content.Context;
+import android.provider.VoicemailContract;
+import android.telecom.PhoneAccountHandle;
+import android.telephony.PhoneStateListener;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import com.android.phone.PhoneUtils;
+import com.android.phone.settings.VisualVoicemailSettingsUtil;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A singleton class designed to remember the active OMTP visual voicemail sources.
+ */
+public class OmtpVvmSourceManager {
+    public static final String TAG = "OmtpVvmSourceManager";
+
+    private static OmtpVvmSourceManager sInstance = new OmtpVvmSourceManager();
+
+    private Context mContext;
+    private SubscriptionManager mSubscriptionManager;
+    private TelephonyManager mTelephonyManager;
+    // Each phone account is associated with a phone state listener for updates to whether the
+    // device is able to sync.
+    private Map<PhoneAccountHandle, PhoneStateListener> mPhoneStateListenerMap;
+
+    /**
+     * Private constructor. Instance should only be acquired through getInstance().
+     */
+    private OmtpVvmSourceManager() {}
+
+    public static OmtpVvmSourceManager getInstance(Context context) {
+        sInstance.setup(context);
+        return sInstance;
+    }
+
+    /**
+     * Set the context and system services so they do not need to be retrieved every time.
+     * @param context The context to get the subscription and telephony manager for.
+     */
+    private void setup(Context context) {
+        if (mContext == null) {
+            mContext = context;
+            mSubscriptionManager = SubscriptionManager.from(context);
+            mTelephonyManager = (TelephonyManager)
+                    mContext.getSystemService(Context.TELEPHONY_SERVICE);
+            mPhoneStateListenerMap = new HashMap<PhoneAccountHandle, PhoneStateListener>();
+        }
+    }
+
+    /**
+     * When a voicemail source is removed, we don't always know which one was removed. Check the
+     * list of registered phone accounts against the active subscriptions list and remove the
+     * inactive accounts.
+     */
+    public void removeInactiveSources() {
+        Set<PhoneAccountHandle> sources = getOmtpVvmSources();
+        for (PhoneAccountHandle source : sources) {
+            if (!PhoneUtils.isPhoneAccountActive(mSubscriptionManager, source)) {
+                VoicemailContract.Status.setStatus(mContext, source,
+                        VoicemailContract.Status.CONFIGURATION_STATE_NOT_CONFIGURED,
+                        VoicemailContract.Status.DATA_CHANNEL_STATE_NO_CONNECTION,
+                        VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_NO_CONNECTION);
+                removePhoneStateListener(source);
+                VisualVoicemailSettingsUtil.setVisualVoicemailEnabled(mContext, source, false);
+            }
+        }
+    }
+
+    public void addPhoneStateListener(PhoneAccountHandle phoneAccount) {
+        if (!mPhoneStateListenerMap.containsKey(phoneAccount)) {
+            VvmPhoneStateListener phoneStateListener = new VvmPhoneStateListener(mContext,
+                    PhoneUtils.makePstnPhoneAccountHandle(phoneAccount.getId()));
+            mPhoneStateListenerMap.put(phoneAccount, phoneStateListener);
+            mTelephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
+        }
+    }
+
+    public void removePhoneStateListener(PhoneAccountHandle phoneAccount) {
+        PhoneStateListener phoneStateListener =
+                mPhoneStateListenerMap.remove(phoneAccount);
+        mTelephonyManager.listen(phoneStateListener, 0);
+    }
+
+    public Set<PhoneAccountHandle> getOmtpVvmSources() {
+        return mPhoneStateListenerMap.keySet();
+    }
+
+    /**
+     * Check if a certain account is registered.
+     *
+     * @param phoneAccount The account to look for.
+     * @return {@code true} if the account is in the list of registered OMTP voicemail sync
+     * accounts. {@code false} otherwise.
+     */
+    public boolean isVvmSourceRegistered(PhoneAccountHandle phoneAccount) {
+        if (phoneAccount == null) {
+            return false;
+        }
+
+        Set<PhoneAccountHandle> sources = getOmtpVvmSources();
+        for (PhoneAccountHandle source : sources) {
+            if (phoneAccount.equals(source)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncAccountManager.java b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncAccountManager.java
deleted file mode 100644
index 6554b71..0000000
--- a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncAccountManager.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2015 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.phone.vvm.omtp.sync;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.provider.VoicemailContract;
-import android.telecom.PhoneAccountHandle;
-import android.telephony.PhoneStateListener;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-
-import com.android.phone.PhoneUtils;
-import com.android.phone.vvm.omtp.OmtpConstants;
-import com.android.phone.vvm.omtp.sms.StatusMessage;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A singleton class designed to assist in OMTP visual voicemail sync behavior.
- */
-public class OmtpVvmSyncAccountManager {
-    public static final String TAG = "OmtpVvmSyncAccountManager";
-    // Constants
-    // The authority for the sync adapter's content provider
-    public static final String AUTHORITY = "com.android.voicemail";
-    // An account type, in the form of a domain name
-    public static final String ACCOUNT_TYPE = "com.android.phone.vvm.omtp";
-
-    private static OmtpVvmSyncAccountManager sInstance = new OmtpVvmSyncAccountManager();
-
-    private Context mContext;
-    private SubscriptionManager mSubscriptionManager;
-    private AccountManager mAccountManager;
-    private TelephonyManager mTelephonyManager;
-    // Each account is associated with a phone state listener for updates to whether the device
-    // is able to sync.
-    private Map<Account, PhoneStateListener> mPhoneStateListenerMap;
-
-    /**
-     * Private constructor. Instance should only be acquired through getInstance().
-     */
-    private OmtpVvmSyncAccountManager() {}
-
-    public static OmtpVvmSyncAccountManager getInstance(Context context) {
-        sInstance.setup(context);
-        return sInstance;
-    }
-
-    /**
-     * Set the context and system services so they do not need to be retrieved every time.
-     * @param context The context to get the account manager and subscription manager for.
-     */
-    private void setup(Context context) {
-        if (mContext == null) {
-            mContext = context;
-            mSubscriptionManager = SubscriptionManager.from(context);
-            mAccountManager = AccountManager.get(context);
-            mTelephonyManager = (TelephonyManager)
-                    mContext.getSystemService(Context.TELEPHONY_SERVICE);
-            mPhoneStateListenerMap = new HashMap<Account, PhoneStateListener>();
-        }
-    }
-
-    /**
-     * Register a sync account. There should be a one to one mapping of sync account to voicemail
-     * source. These sync accounts primarily service the purpose of keeping track of how many OMTP
-     * voicemail sources are active and which phone accounts they correspond to.
-     *
-     * @param account The account to register
-     */
-    public void createSyncAccount(Account account) {
-        // Add the account and account type, no password or user data
-        if (mAccountManager.addAccountExplicitly(account, null, null)) {
-             ContentResolver.setIsSyncable(account, AUTHORITY, 1);
-             ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
-        } else {
-            Log.w(TAG, "Attempted to re-register existing account.");
-        }
-    }
-
-    /**
-     * When a voicemail source is removed, we don't always know which one was removed. Check the
-     * list of registered sync accounts against the active subscriptions list and remove the
-     * inactive accounts.
-     */
-    public void removeInactiveAccounts() {
-        Account[] registeredAccounts = mAccountManager.getAccountsByType(ACCOUNT_TYPE);
-        for (int i = 0; i < registeredAccounts.length; i++) {
-            PhoneAccountHandle handle = PhoneUtils.makePstnPhoneAccountHandle(
-                    registeredAccounts[i].name);
-            if (!PhoneUtils.isPhoneAccountActive(mSubscriptionManager, handle)) {
-                mAccountManager.removeAccount(registeredAccounts[i], null, null, null);
-                VoicemailContract.Status.setStatus(mContext, handle,
-                        VoicemailContract.Status.CONFIGURATION_STATE_NOT_CONFIGURED,
-                        VoicemailContract.Status.DATA_CHANNEL_STATE_NO_CONNECTION,
-                        VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_NO_CONNECTION);
-
-                removePhoneStateListener(registeredAccounts[i]);
-            }
-        }
-    }
-
-    public void addPhoneStateListener(Account account) {
-        if (!mPhoneStateListenerMap.containsKey(account)) {
-            VvmPhoneStateListener phoneStateListener = new VvmPhoneStateListener(mContext,
-                    PhoneUtils.makePstnPhoneAccountHandle(account.name));
-            mPhoneStateListenerMap.put(account, phoneStateListener);
-            mTelephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
-        }
-    }
-
-    public void removePhoneStateListener(Account account) {
-        PhoneStateListener phoneStateListener =
-                mPhoneStateListenerMap.remove(account);
-        mTelephonyManager.listen(phoneStateListener, 0);
-    }
-
-    public Account[] getOmtpAccounts() {
-        return mAccountManager.getAccountsByType(ACCOUNT_TYPE);
-    }
-
-    /**
-     * Check if a certain account is registered.
-     *
-     * @param account The account to look for.
-     * @return {@code true} if the account is in the list of registered OMTP voicemail sync
-     * accounts. {@code false} otherwise.
-     */
-    public boolean isAccountRegistered(Account account) {
-        Account[] accounts = getOmtpAccounts();
-        for (int i = 0; i < accounts.length; i++) {
-            if (account.equals(accounts[i])) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Set the IMAP credentials as extra fields in the account.
-     *
-     * @param account The account to add credentials to.
-     * @param message The status message to extract the fields from.
-     */
-    public void setAccountCredentialsFromStatusMessage(Account account, StatusMessage message) {
-        mAccountManager.setUserData(account, OmtpConstants.IMAP_PORT, message.getImapPort());
-        mAccountManager.setUserData(account, OmtpConstants.SERVER_ADDRESS,
-                message.getServerAddress());
-        mAccountManager.setUserData(account, OmtpConstants.IMAP_USER_NAME,
-                message.getImapUserName());
-        mAccountManager.setUserData(account, OmtpConstants.IMAP_PASSWORD,
-                message.getImapPassword());
-    }
-}
diff --git a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
index 0a6b5c1..b5bd51f 100644
--- a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
+++ b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
@@ -15,7 +15,6 @@
  */
 package com.android.phone.vvm.omtp.sync;
 
-import android.accounts.Account;
 import android.app.IntentService;
 import android.content.Context;
 import android.content.Intent;
@@ -25,15 +24,18 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
 import android.provider.VoicemailContract;
+import android.telecom.PhoneAccountHandle;
 import android.telecom.Voicemail;
 import android.util.Log;
 
 import com.android.phone.PhoneUtils;
+import com.android.phone.settings.VisualVoicemailSettingsUtil;
 import com.android.phone.vvm.omtp.imap.ImapHelper;
 
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Sync OMTP visual voicemail.
@@ -48,7 +50,7 @@
     /** Only download from the server. */
     public static final String SYNC_DOWNLOAD_ONLY = "download_only";
     /** The account to sync. */
-    public static final String EXTRA_ACCOUNT = "account";
+    public static final String EXTRA_PHONE_ACCOUNT = "phone_account";
 
     // Timeout used to call ConnectivityManager.requestNetwork
     private static final int NETWORK_REQUEST_TIMEOUT_MILLIS = 60 * 1000;
@@ -75,48 +77,55 @@
         }
 
         String action = intent.getAction();
-        OmtpVvmSyncAccountManager syncAccountManager = OmtpVvmSyncAccountManager.getInstance(this);
-        Account account = intent.getParcelableExtra(EXTRA_ACCOUNT);
-        if (account != null && syncAccountManager.isAccountRegistered(account)) {
-            Log.v(TAG, "Sync requested: " + action + " - for account: " + account.name);
-            doSync(account, action);
+        PhoneAccountHandle phoneAccount = intent.getParcelableExtra(EXTRA_PHONE_ACCOUNT);
+        if (phoneAccount != null) {
+            Log.v(TAG, "Sync requested: " + action + " - for account: " + phoneAccount);
+            doSync(phoneAccount, action);
         } else {
             Log.v(TAG, "Sync requested: " + action + " - for all accounts");
-            Account[] accounts = syncAccountManager.getOmtpAccounts();
-            for (int i = 0; i < accounts.length; i++) {
-                doSync(accounts[i], action);
+            OmtpVvmSourceManager vvmSourceManager =
+                    OmtpVvmSourceManager.getInstance(this);
+            Set<PhoneAccountHandle> sources = vvmSourceManager.getOmtpVvmSources();
+            for (PhoneAccountHandle source : sources) {
+                doSync(source, action);
             }
         }
     }
 
-    private void doSync(Account account, String action) {
-        int subId = PhoneUtils.getSubIdForPhoneAccountHandle(
-                PhoneUtils.makePstnPhoneAccountHandle(account.name));
+    private void doSync(PhoneAccountHandle phoneAccount, String action) {
+        if (!VisualVoicemailSettingsUtil.getVisualVoicemailEnabled(this, phoneAccount)) {
+            Log.v(TAG, "Sync requested for disabled account");
+            return;
+        }
+
+        int subId = PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccount);
 
         NetworkRequest networkRequest = new NetworkRequest.Builder()
                 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
                 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                 .setNetworkSpecifier(Integer.toString(subId))
                 .build();
-        NetworkCallback networkCallback = new OmtpVvmNetworkRequestCallback(this, account, action);
+        NetworkCallback networkCallback = new OmtpVvmNetworkRequestCallback(this, phoneAccount,
+                action);
         getConnectivityManager().requestNetwork(
                 networkRequest, networkCallback, NETWORK_REQUEST_TIMEOUT_MILLIS);
     }
 
     private class OmtpVvmNetworkRequestCallback extends ConnectivityManager.NetworkCallback {
         Context mContext;
-        Account mAccount;
+        PhoneAccountHandle mPhoneAccount;
         String mAction;
 
-        public OmtpVvmNetworkRequestCallback(Context context, Account account, String action) {
+        public OmtpVvmNetworkRequestCallback(Context context, PhoneAccountHandle phoneAccount,
+                String action) {
             mContext = context;
-            mAccount = account;
+            mPhoneAccount = phoneAccount;
             mAction = action;
         }
 
         @Override
         public void onAvailable(final Network network) {
-            ImapHelper imapHelper = new ImapHelper(mContext, mAccount, network);
+            ImapHelper imapHelper = new ImapHelper(mContext, mPhoneAccount, network);
             if (SYNC_FULL_SYNC.equals(mAction) || SYNC_UPLOAD_ONLY.equals(mAction)) {
                 upload(imapHelper);
             }
diff --git a/src/com/android/phone/vvm/omtp/sync/VoicemailProviderChangeReceiver.java b/src/com/android/phone/vvm/omtp/sync/VoicemailProviderChangeReceiver.java
index fc1823e..0885d65 100644
--- a/src/com/android/phone/vvm/omtp/sync/VoicemailProviderChangeReceiver.java
+++ b/src/com/android/phone/vvm/omtp/sync/VoicemailProviderChangeReceiver.java
@@ -18,6 +18,7 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.provider.VoicemailContract;
 
 /**
  * Receives changes to the voicemail provider so they can be sent to the voicemail server.
@@ -25,9 +26,10 @@
 public class VoicemailProviderChangeReceiver extends BroadcastReceiver {
     @Override
     public void onReceive(Context context, Intent intent) {
-        OmtpVvmSyncAccountManager syncAccountManager =
-                OmtpVvmSyncAccountManager.getInstance(context);
-        if (syncAccountManager.getOmtpAccounts().length > 0) {
+        boolean isSelfChanged = intent.getBooleanExtra(VoicemailContract.EXTRA_SELF_CHANGE, false);
+        OmtpVvmSourceManager vvmSourceManager =
+                OmtpVvmSourceManager.getInstance(context);
+        if (vvmSourceManager.getOmtpVvmSources().size() > 0 && !isSelfChanged) {
             Intent serviceIntent = new Intent(context, OmtpVvmSyncService.class);
             serviceIntent.setAction(OmtpVvmSyncService.SYNC_UPLOAD_ONLY);
             context.startService(serviceIntent);