Merge "Communicating participant changes to conference controller." into lmp-mr1-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 88020fc..5d9f835 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -134,8 +134,9 @@
     <!-- Entry in dialog to "ask first" for accounts when making a call -->
     <string name="phone_accounts_ask_every_time">Ask first</string>
 
-    <!-- Label for heading of the accounts section in the phone accounts settings screen. -->
-    <string name="phone_accounts_accounts_header">Accounts</string>
+    <!-- Label for heading of the per-account settings section in the phone accounts settings
+         screen. -->
+    <string name="phone_accounts_settings_header">Settings</string>
     <!-- Label for invoking phone account selection screen -->
     <string name="phone_accounts_choose_accounts">Choose accounts</string>
     <!-- Label for heading in the phone account selection screen -->
@@ -1228,9 +1229,9 @@
     <string name="enable_video_calling_title">Turn on video calling</string>
 
     <!-- Message for dialog shown when the user tries to turn on video calling but enhanced 4G LTE
-         is disabled. -->
+         is disabled. They have to turn on Enhanced 4G LTE capability in network settings first. -->
     <string name="enable_video_calling_dialog_msg">
-        To turn on video calling, you need to enable Enhanced 4G LTE Mode in system settings.
+        To turn on video calling, you need to enable Enhanced 4G LTE Mode in network settings.
     </string>
 
     <!-- Label for action button in dialog which opens mobile network settings, for video calling
diff --git a/res/xml/call_feature_setting.xml b/res/xml/call_feature_setting.xml
index 2148594..f958c1a 100644
--- a/res/xml/call_feature_setting.xml
+++ b/res/xml/call_feature_setting.xml
@@ -64,7 +64,7 @@
 
         </PreferenceScreen>
 
-        <RingtonePreference
+        <com.android.phone.settings.VoicemailRingtonePreference
             android:key="button_voicemail_notification_ringtone_key"
             android:title="@string/voicemail_notification_ringtone_title"
             android:persistent="true"
diff --git a/res/xml/phone_account_settings.xml b/res/xml/phone_account_settings.xml
index abb4995..bf62ed0 100644
--- a/res/xml/phone_account_settings.xml
+++ b/res/xml/phone_account_settings.xml
@@ -18,6 +18,10 @@
     xmlns:phone="http://schemas.android.com/apk/res/com.android.phone"
     android:title="@string/phone_accounts">
 
+    <PreferenceCategory
+        android:key="phone_accounts_accounts_list_category_key"
+        android:title="@string/phone_accounts_settings_header" />
+
     <com.android.phone.settings.AccountSelectionPreference
         android:key="default_outgoing_account"
         android:title="@string/phone_accounts_make_calls_with"
diff --git a/sip/src/com/android/services/telephony/sip/SipUtil.java b/sip/src/com/android/services/telephony/sip/SipUtil.java
index f93f02d..df1a03a 100644
--- a/sip/src/com/android/services/telephony/sip/SipUtil.java
+++ b/sip/src/com/android/services/telephony/sip/SipUtil.java
@@ -22,6 +22,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.net.sip.SipManager;
 import android.net.sip.SipProfile;
@@ -118,7 +119,9 @@
                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
                 .setAddress(Uri.parse(profile.getUriString()))
                 .setShortDescription(profile.getDisplayName())
-                .setIconResId(R.drawable.ic_dialer_sip_black_24dp)
+                .setIconBitmap(BitmapFactory.decodeResource(
+                        context.getResources(),
+                        R.drawable.ic_dialer_sip_black_24dp))
                 .setSupportedUriSchemes(supportedUriSchemes);
 
         return builder.build();
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index 7c828f9..059a7f5 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -33,7 +33,6 @@
 import android.content.pm.ResolveInfo;
 import android.database.Cursor;
 import android.media.AudioManager;
-import android.media.RingtoneManager;
 import android.os.AsyncResult;
 import android.os.Bundle;
 import android.os.Handler;
@@ -50,18 +49,21 @@
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
 import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.MenuItem;
 import android.view.WindowManager;
 import android.widget.ListAdapter;
 
+import com.android.ims.ImsManager;
 import com.android.internal.telephony.CallForwardInfo;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.phone.common.util.SettingsUtil;
 import com.android.phone.settings.AccountSelectionPreference;
+import com.android.phone.settings.VoicemailProviderSettings;
 import com.android.services.telephony.sip.SipUtil;
 
 import java.lang.String;
@@ -112,6 +114,13 @@
     // to trigger its configuration UI
     public static final String ACTION_CONFIGURE_VOICEMAIL =
             "com.android.phone.CallFeaturesSetting.CONFIGURE_VOICEMAIL";
+    // Extra on intent to Call Settings containing the id of the subscription to modify.
+    public static final String SUB_ID_EXTRA =
+            "com.android.phone.CallFeaturesSetting.SubscriptionId";
+    // Extra on intent to Call Settings containing the label of the subscription to modify.
+    public static final String SUB_LABEL_EXTRA =
+            "com.android.phone.CallFeaturesSetting.SubscriptionLabel";
+
     // Extra put in the return from VM provider config containing voicemail number to set
     public static final String VM_NUMBER_EXTRA = "com.android.phone.VoicemailNumber";
     // Extra put in the return from VM provider config containing call forwarding number to set
@@ -121,13 +130,7 @@
     // If the VM provider returns non null value in this extra we will force the user to
     // choose another VM provider
     public static final String SIGNOUT_EXTRA = "com.android.phone.Signout";
-    //Information about logical "up" Activity
-    private static final String UP_ACTIVITY_PACKAGE = "com.android.dialer";
-    private static final String UP_ACTIVITY_CLASS =
-            "com.android.dialer.DialtactsActivity";
 
-    // Used to tell the saving logic to leave forwarding number as is
-    public static final CallForwardInfo[] FWD_SETTINGS_DONT_TOUCH = null;
     // Suffix appended to provider key for storing vm number
     public static final String VM_NUMBER_TAG = "#VMNumber";
     // Suffix appended to provider key for storing forwarding settings
@@ -188,8 +191,6 @@
 
     private static final String ENABLE_VIDEO_CALLING_KEY = "button_enable_video_calling";
 
-    private Intent mContactListIntent;
-
     /** Event for Async voicemail change call */
     private static final int EVENT_VOICEMAIL_CHANGED        = 500;
     private static final int EVENT_FORWARDING_CHANGED       = 501;
@@ -237,18 +238,6 @@
 
     private EditPhoneNumberPreference mSubMenuVoicemailSettings;
 
-    private Runnable mVoicemailRingtoneLookupRunnable;
-    private final Handler mVoicemailRingtoneLookupComplete = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY:
-                    mVoicemailNotificationRingtone.setSummary((CharSequence) msg.obj);
-                    break;
-            }
-        }
-    };
-
     /** Whether dialpad plays DTMF tone or not. */
     private CheckBoxPreference mButtonAutoRetry;
     private CheckBoxPreference mButtonHAC;
@@ -258,9 +247,7 @@
     private ListPreference mVoicemailProviders;
     private PreferenceScreen mVoicemailSettingsScreen;
     private PreferenceScreen mVoicemailSettings;
-    private Preference mVoicemailNotificationRingtone;
     private CheckBoxPreference mVoicemailNotificationVibrate;
-    private AccountSelectionPreference mDefaultOutgoingAccount;
     private CheckBoxPreference mEnableVideoCalling;
 
     private class VoiceMailProvider {
@@ -272,90 +259,6 @@
         public Intent intent;
     }
 
-    /**
-     * Forwarding settings we are going to save.
-     */
-    private static final int [] FORWARDING_SETTINGS_REASONS = new int[] {
-        CommandsInterface.CF_REASON_UNCONDITIONAL,
-        CommandsInterface.CF_REASON_BUSY,
-        CommandsInterface.CF_REASON_NO_REPLY,
-        CommandsInterface.CF_REASON_NOT_REACHABLE
-    };
-
-    private class VoiceMailProviderSettings {
-        /**
-         * Constructs settings object, setting all conditional forwarding to the specified number
-         */
-        public VoiceMailProviderSettings(String voicemailNumber, String forwardingNumber,
-                int timeSeconds) {
-            this.voicemailNumber = voicemailNumber;
-            if (forwardingNumber == null || forwardingNumber.length() == 0) {
-                this.forwardingSettings = FWD_SETTINGS_DONT_TOUCH;
-            } else {
-                this.forwardingSettings = new CallForwardInfo[FORWARDING_SETTINGS_REASONS.length];
-                for (int i = 0; i < this.forwardingSettings.length; i++) {
-                    CallForwardInfo fi = new CallForwardInfo();
-                    this.forwardingSettings[i] = fi;
-                    fi.reason = FORWARDING_SETTINGS_REASONS[i];
-                    fi.status = (fi.reason == CommandsInterface.CF_REASON_UNCONDITIONAL) ? 0 : 1;
-                    fi.serviceClass = CommandsInterface.SERVICE_CLASS_VOICE;
-                    fi.toa = PhoneNumberUtils.TOA_International;
-                    fi.number = forwardingNumber;
-                    fi.timeSeconds = timeSeconds;
-                }
-            }
-        }
-
-        public VoiceMailProviderSettings(String voicemailNumber, CallForwardInfo[] infos) {
-            this.voicemailNumber = voicemailNumber;
-            this.forwardingSettings = infos;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (o == null) return false;
-            if (!(o instanceof VoiceMailProviderSettings)) return false;
-            final VoiceMailProviderSettings v = (VoiceMailProviderSettings)o;
-
-            return ((this.voicemailNumber == null &&
-                        v.voicemailNumber == null) ||
-                    this.voicemailNumber != null &&
-                        this.voicemailNumber.equals(v.voicemailNumber))
-                    &&
-                    forwardingSettingsEqual(this.forwardingSettings,
-                            v.forwardingSettings);
-        }
-
-        private boolean forwardingSettingsEqual(CallForwardInfo[] infos1,
-                CallForwardInfo[] infos2) {
-            if (infos1 == infos2) return true;
-            if (infos1 == null || infos2 == null) return false;
-            if (infos1.length != infos2.length) return false;
-            for (int i = 0; i < infos1.length; i++) {
-                CallForwardInfo i1 = infos1[i];
-                CallForwardInfo i2 = infos2[i];
-                if (i1.status != i2.status ||
-                    i1.reason != i2.reason ||
-                    i1.serviceClass != i2.serviceClass ||
-                    i1.toa != i2.toa ||
-                    i1.number != i2.number ||
-                    i1.timeSeconds != i2.timeSeconds) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        @Override
-        public String toString() {
-            return voicemailNumber + ((forwardingSettings != null ) ? (", " +
-                    forwardingSettings.toString()) : "");
-        }
-
-        public String voicemailNumber;
-        public CallForwardInfo[] forwardingSettings;
-    }
-
     private SharedPreferences mPerProviderSavedVMNumbers;
 
     /**
@@ -562,7 +465,7 @@
             }
             updateVMPreferenceWidgets(newProviderKey);
 
-            final VoiceMailProviderSettings newProviderSettings =
+            final VoicemailProviderSettings newProviderSettings =
                     loadSettingsForVoiceMailProvider(newProviderKey);
 
             // If the user switches to a voice mail provider and we have a
@@ -583,7 +486,27 @@
                 saveVoiceMailAndForwardingNumber(newProviderKey, newProviderSettings);
             }
         } else if (preference == mEnableVideoCalling) {
-            PhoneGlobals.getInstance().phoneMgr.enableVideoCalling((boolean) objValue);
+            if (ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())) {
+                PhoneGlobals.getInstance().phoneMgr.enableVideoCalling((boolean) objValue);
+            } else {
+                AlertDialog.Builder builder = new AlertDialog.Builder(this);
+                DialogInterface.OnClickListener networkSettingsClickListener =
+                        new Dialog.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                                startActivity(new Intent(mPhone.getContext(),
+                                        com.android.phone.MobileNetworkSettings.class));
+                            }
+                        };
+                builder.setMessage(getResources().getString(
+                                R.string.enable_video_calling_dialog_msg))
+                        .setNeutralButton(getResources().getString(
+                                R.string.enable_video_calling_dialog_settings),
+                                networkSettingsClickListener)
+                        .setPositiveButton(android.R.string.ok, null)
+                        .show();
+                return false;
+            }
         }
         // always let the preference setting proceed.
         return true;
@@ -655,11 +578,11 @@
                 }
 
                 showDialogIfForeground(VOICEMAIL_REVERTING_DIALOG);
-                final VoiceMailProviderSettings prevSettings =
+                final VoicemailProviderSettings prevSettings =
                         loadSettingsForVoiceMailProvider(mPreviousVMProviderKey);
                 if (prevSettings == null) {
                     // prevSettings never becomes null since it should be already loaded!
-                    Log.e(LOG_TAG, "VoiceMailProviderSettings for the key \""
+                    Log.e(LOG_TAG, "VoicemailProviderSettings for the key \""
                             + mPreviousVMProviderKey + "\" becomes null, which is unexpected.");
                     if (DBG) {
                         Log.e(LOG_TAG,
@@ -668,7 +591,7 @@
                     }
                 }
                 if (mVMChangeCompletedSuccessfully) {
-                    mNewVMNumber = prevSettings.voicemailNumber;
+                    mNewVMNumber = prevSettings.getVoicemailNumber();
                     Log.i(LOG_TAG, "VM change is already completed successfully."
                             + "Have to revert VM back to " + mNewVMNumber + " again.");
                     mPhone.setVoiceMailNumber(
@@ -678,8 +601,7 @@
                 }
                 if (mFwdChangesRequireRollback) {
                     Log.i(LOG_TAG, "Requested to rollback Fwd changes.");
-                    final CallForwardInfo[] prevFwdSettings =
-                        prevSettings.forwardingSettings;
+                    final CallForwardInfo[] prevFwdSettings = prevSettings.getForwardingSettings();
                     if (prevFwdSettings != null) {
                         Map<Integer, AsyncResult> results =
                             mForwardingChangeResults;
@@ -790,7 +712,7 @@
             if (DBG) log("onActivityResult: vm provider cfg result " +
                     (fwdNum != null ? "has" : " does not have") + " forwarding number");
             saveVoiceMailAndForwardingNumber(getCurrentVoicemailProviderKey(),
-                    new VoiceMailProviderSettings(vmNum, fwdNum, fwdNumTime));
+                    new VoicemailProviderSettings(vmNum, fwdNum, fwdNumTime));
             return;
         }
 
@@ -829,8 +751,8 @@
 
         saveVoiceMailAndForwardingNumber(
                 getCurrentVoicemailProviderKey(),
-                new VoiceMailProviderSettings(mSubMenuVoicemailSettings.getPhoneNumber(),
-                        FWD_SETTINGS_DONT_TOUCH)
+                new VoicemailProviderSettings(mSubMenuVoicemailSettings.getPhoneNumber(),
+                        VoicemailProviderSettings.NO_FORWARDING)
         );
     }
 
@@ -875,28 +797,29 @@
         }
     }
 
-    private void saveVoiceMailAndForwardingNumber(String key,
-            VoiceMailProviderSettings newSettings) {
+    private void saveVoiceMailAndForwardingNumber(
+            String key, VoicemailProviderSettings newSettings) {
         if (DBG) log("saveVoiceMailAndForwardingNumber: " + newSettings.toString());
-        mNewVMNumber = newSettings.voicemailNumber;
+        mNewVMNumber = newSettings.getVoicemailNumber();
         // empty vm number == clearing the vm number ?
         if (mNewVMNumber == null) {
             mNewVMNumber = "";
         }
 
-        mNewFwdSettings = newSettings.forwardingSettings;
-        if (DBG) log("newFwdNumber " +
-                String.valueOf((mNewFwdSettings != null ? mNewFwdSettings.length : 0))
+        mNewFwdSettings = newSettings.getForwardingSettings();
+        if (DBG) log("newFwdNumber "
+                + String.valueOf((mNewFwdSettings != null ? mNewFwdSettings.length : 0))
                 + " settings");
 
         // No fwd settings on CDMA
         if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
             if (DBG) log("ignoring forwarding setting since this is CDMA phone");
-            mNewFwdSettings = FWD_SETTINGS_DONT_TOUCH;
+            mNewFwdSettings = VoicemailProviderSettings.NO_FORWARDING;
         }
 
-        //throw a warning if the vm is the same and we do not touch forwarding.
-        if (mNewVMNumber.equals(mOldVmNumber) && mNewFwdSettings == FWD_SETTINGS_DONT_TOUCH) {
+        // Throw a warning if the voicemail is the same and we did not change forwarding.
+        if (mNewVMNumber.equals(mOldVmNumber)
+                && mNewFwdSettings == VoicemailProviderSettings.NO_FORWARDING) {
             showVMDialog(MSG_VM_NOCHANGE);
             return;
         }
@@ -909,10 +832,11 @@
             mReadingSettingsForDefaultProvider =
                     mPreviousVMProviderKey.equals(DEFAULT_VM_PROVIDER_KEY);
             if (DBG) log("Reading current forwarding settings");
-            mForwardingReadResults = new CallForwardInfo[FORWARDING_SETTINGS_REASONS.length];
-            for (int i = 0; i < FORWARDING_SETTINGS_REASONS.length; i++) {
-                mForwardingReadResults[i] = null;
-                mPhone.getCallForwardingOption(FORWARDING_SETTINGS_REASONS[i],
+            int numSettingsReasons = VoicemailProviderSettings.FORWARDING_SETTINGS_REASONS.length;
+            mForwardingReadResults = new CallForwardInfo[numSettingsReasons];
+            for (int i = 0; i < mForwardingReadResults.length; i++) {
+                mPhone.getCallForwardingOption(
+                        VoicemailProviderSettings.FORWARDING_SETTINGS_REASONS[i],
                         mGetOptionComplete.obtainMessage(EVENT_FORWARDING_GET_COMPLETED, i, 0));
             }
             showDialogIfForeground(VOICEMAIL_FWD_READING_DIALOG);
@@ -978,7 +902,7 @@
             if (DBG) Log.d(LOG_TAG, "Creating default info for " + idx);
             fi = new CallForwardInfo();
             fi.status = 0;
-            fi.reason = FORWARDING_SETTINGS_REASONS[idx];
+            fi.reason = VoicemailProviderSettings.FORWARDING_SETTINGS_REASONS[idx];
             fi.serviceClass = CommandsInterface.SERVICE_CLASS_VOICE;
         } else {
             // if there is not a forwarding number, ensure the entry is set to "not active."
@@ -1003,7 +927,7 @@
             dismissDialogSafely(VOICEMAIL_FWD_READING_DIALOG);
             if (mReadingSettingsForDefaultProvider) {
                 maybeSaveSettingsForVoicemailProvider(DEFAULT_VM_PROVIDER_KEY,
-                        new VoiceMailProviderSettings(this.mOldVmNumber,
+                        new VoicemailProviderSettings(this.mOldVmNumber,
                                 mForwardingReadResults));
                 mReadingSettingsForDefaultProvider = false;
             }
@@ -1049,7 +973,7 @@
     private void saveVoiceMailAndForwardingNumberStage2() {
         mForwardingChangeResults = null;
         mVoicemailChangeResult = null;
-        if (mNewFwdSettings != FWD_SETTINGS_DONT_TOUCH) {
+        if (mNewFwdSettings != VoicemailProviderSettings.NO_FORWARDING) {
             resetForwardingChangeState();
             for (int i = 0; i < mNewFwdSettings.length; i++) {
                 CallForwardInfo fi = mNewFwdSettings[i];
@@ -1498,24 +1422,6 @@
         mPhone = PhoneGlobals.getPhone();
         mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
 
-        // create intent to bring up contact list
-        mContactListIntent = new Intent(Intent.ACTION_GET_CONTENT);
-        mContactListIntent.setType(android.provider.Contacts.Phones.CONTENT_ITEM_TYPE);
-
-        mVoicemailRingtoneLookupRunnable = new Runnable() {
-            @Override
-            public void run() {
-                if (mVoicemailNotificationRingtone != null) {
-                    SettingsUtil.updateRingtoneName(
-                            mPhone.getContext(),
-                            mVoicemailRingtoneLookupComplete,
-                            RingtoneManager.TYPE_NOTIFICATION,
-                            mVoicemailNotificationRingtone,
-                            MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY);
-                }
-            }
-        };
-
         // Show the voicemail preference in onResume if the calling intent specifies the
         // ACTION_ADD_VOICEMAIL action.
         mShowVoicemailPreference = (icicle == null) &&
@@ -1526,10 +1432,11 @@
         mPhoneAccountSettingsPreference = findPreference(PHONE_ACCOUNT_SETTINGS_KEY);
 
         TelecomManager telecomManager = TelecomManager.from(this);
+        TelephonyManager telephonyManager =
+                (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
 
-        if (telecomManager.getAllPhoneAccountsCount() <= 1
-                && telecomManager.getSimCallManagers().isEmpty()
-                && !SipUtil.isVoipSupported(this)) {
+        if ((telecomManager.getSimCallManagers().isEmpty() && !SipUtil.isVoipSupported(this))
+                || telephonyManager.getPhoneCount() > 1) {
             getPreferenceScreen().removePreference(mPhoneAccountSettingsPreference);
         }
     }
@@ -1552,7 +1459,6 @@
         addPreferencesFromResource(R.xml.call_feature_setting);
         initPhoneAccountPreferences();
 
-        // get buttons
         PreferenceScreen prefSet = getPreferenceScreen();
         mSubMenuVoicemailSettings = (EditPhoneNumberPreference) findPreference(BUTTON_VOICEMAIL_KEY);
         mSubMenuVoicemailSettings.setParentActivity(this, VOICEMAIL_PREF_ID, this);
@@ -1564,20 +1470,15 @@
         mButtonHAC = (CheckBoxPreference) findPreference(BUTTON_HAC_KEY);
         mButtonTTY = (ListPreference) findPreference(BUTTON_TTY_KEY);
         mVoicemailProviders = (ListPreference) findPreference(BUTTON_VOICEMAIL_PROVIDER_KEY);
-        CheckBoxPreference mEnableVideoCalling =
-                (CheckBoxPreference) findPreference(ENABLE_VIDEO_CALLING_KEY);
+        mEnableVideoCalling = (CheckBoxPreference) findPreference(ENABLE_VIDEO_CALLING_KEY);
 
-        if (mVoicemailProviders != null) {
-            mVoicemailProviders.setOnPreferenceChangeListener(this);
-            mVoicemailSettingsScreen =
-                    (PreferenceScreen) findPreference(VOICEMAIL_SETTING_SCREEN_PREF_KEY);
-            mVoicemailSettings = (PreferenceScreen)findPreference(BUTTON_VOICEMAIL_SETTING_KEY);
-            mVoicemailNotificationRingtone =
-                    findPreference(BUTTON_VOICEMAIL_NOTIFICATION_RINGTONE_KEY);
-            mVoicemailNotificationVibrate =
-                    (CheckBoxPreference) findPreference(BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY);
-            initVoiceMailProviders();
-        }
+        mVoicemailProviders.setOnPreferenceChangeListener(this);
+        mVoicemailSettingsScreen =
+                (PreferenceScreen) findPreference(VOICEMAIL_SETTING_SCREEN_PREF_KEY);
+        mVoicemailSettings = (PreferenceScreen)findPreference(BUTTON_VOICEMAIL_SETTING_KEY);
+        mVoicemailNotificationVibrate =
+                (CheckBoxPreference) findPreference(BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY);
+        initVoiceMailProviders();
 
 
         if (getResources().getBoolean(R.bool.dtmf_type_enabled)) {
@@ -1655,7 +1556,7 @@
         // If we have at least one non default VM provider registered then bring up
         // the selection for the VM provider, otherwise bring up a VM number dialog.
         // We only bring up the dialog the first time we are called (not after orientation change)
-        if (mShowVoicemailPreference && mVoicemailProviders != null) {
+        if (mShowVoicemailPreference) {
             if (DBG) {
                 log("ACTION_ADD_VOICEMAIL Intent is thrown. current VM data size: "
                         + mVMProvidersData.size());
@@ -1679,16 +1580,15 @@
                     BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY, false));
         }
 
-        if (ImsUtil.isImsEnabled(mPhone.getContext()) && ENABLE_VT_FLAG) {
-            mEnableVideoCalling.setChecked(
-                    PhoneGlobals.getInstance().phoneMgr.isVideoCallingEnabled());
+        if (ImsManager.isVtEnabledByPlatform(mPhone.getContext()) && ENABLE_VT_FLAG) {
+            boolean currentValue =
+                    ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())
+                    ? PhoneGlobals.getInstance().phoneMgr.isVideoCallingEnabled() : false;
+            mEnableVideoCalling.setChecked(currentValue);
             mEnableVideoCalling.setOnPreferenceChangeListener(this);
         } else {
             prefSet.removePreference(mEnableVideoCalling);
         }
-
-        // Look up the voicemail ringtone name asynchronously and update its preference.
-        new Thread(mVoicemailRingtoneLookupRunnable).start();
     }
 
     // Migrate settings from BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_WHEN_KEY to
@@ -1710,11 +1610,6 @@
         return false;
     }
 
-    private boolean isAirplaneModeOn() {
-        return Settings.System.getInt(getContentResolver(),
-                Settings.System.AIRPLANE_MODE_ON, 0) != 0;
-    }
-
     private void handleTTYChange(Preference preference, Object objValue) {
         int buttonTtyMode;
         buttonTtyMode = Integer.valueOf((String) objValue).intValue();
@@ -1929,11 +1824,8 @@
      * Later on these will be used when the user switches a provider.
      */
     private void maybeSaveSettingsForVoicemailProvider(String key,
-            VoiceMailProviderSettings newSettings) {
-        if (mVoicemailProviders == null) {
-            return;
-        }
-        final VoiceMailProviderSettings curSettings = loadSettingsForVoiceMailProvider(key);
+            VoicemailProviderSettings newSettings) {
+        final VoicemailProviderSettings curSettings = loadSettingsForVoiceMailProvider(key);
         if (newSettings.equals(curSettings)) {
             if (DBG) {
                 log("maybeSaveSettingsForVoicemailProvider:"
@@ -1943,10 +1835,10 @@
         }
         if (DBG) log("Saving settings for " + key + ": " + newSettings.toString());
         Editor editor = mPerProviderSavedVMNumbers.edit();
-        editor.putString(key + VM_NUMBER_TAG, newSettings.voicemailNumber);
+        editor.putString(key + VM_NUMBER_TAG, newSettings.getVoicemailNumber());
         String fwdKey = key + FWD_SETTINGS_TAG;
-        CallForwardInfo[] s = newSettings.forwardingSettings;
-        if (s != FWD_SETTINGS_DONT_TOUCH) {
+        CallForwardInfo[] s = newSettings.getForwardingSettings();
+        if (s != VoicemailProviderSettings.NO_FORWARDING) {
             editor.putInt(fwdKey + FWD_SETTINGS_LENGTH_TAG, s.length);
             for (int i = 0; i < s.length; i++) {
                 final String settingKey = fwdKey + FWD_SETTING_TAG + String.valueOf(i);
@@ -1970,7 +1862,7 @@
      * and forwarding number to the stored one. Otherwise we will bring up provider's configuration
      * UI.
      */
-    private VoiceMailProviderSettings loadSettingsForVoiceMailProvider(String key) {
+    private VoicemailProviderSettings loadSettingsForVoiceMailProvider(String key) {
         final String vmNumberSetting = mPerProviderSavedVMNumbers.getString(key + VM_NUMBER_TAG,
                 null);
         if (vmNumberSetting == null) {
@@ -1979,7 +1871,7 @@
             return null;
         }
 
-        CallForwardInfo[] cfi = FWD_SETTINGS_DONT_TOUCH;
+        CallForwardInfo[] cfi = VoicemailProviderSettings.NO_FORWARDING;
         String fwdKey = key + FWD_SETTINGS_TAG;
         final int fwdLen = mPerProviderSavedVMNumbers.getInt(fwdKey + FWD_SETTINGS_LENGTH_TAG, 0);
         if (fwdLen > 0) {
@@ -2001,7 +1893,7 @@
             }
         }
 
-        VoiceMailProviderSettings settings =  new VoiceMailProviderSettings(vmNumberSetting, cfi);
+        VoicemailProviderSettings settings =  new VoicemailProviderSettings(vmNumberSetting, cfi);
         if (DBG) log("Loaded settings for " + key + ": " + settings.toString());
         return settings;
     }
@@ -2011,9 +1903,6 @@
      */
     private void deleteSettingsForVoicemailProvider(String key) {
         if (DBG) log("Deleting settings for" + key);
-        if (mVoicemailProviders == null) {
-            return;
-        }
         mPerProviderSavedVMNumbers.edit()
             .putString(key + VM_NUMBER_TAG, null)
             .putInt(key + FWD_SETTINGS_TAG + FWD_SETTINGS_LENGTH_TAG, 0)
diff --git a/src/com/android/phone/ImsUtil.java b/src/com/android/phone/ImsUtil.java
index 4f7eb7f..c3d780b 100644
--- a/src/com/android/phone/ImsUtil.java
+++ b/src/com/android/phone/ImsUtil.java
@@ -16,18 +16,10 @@
 
 package com.android.phone;
 
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.provider.Settings.SettingNotFoundException;
-import android.util.Log;
-
-import com.android.internal.telephony.Phone;
 import com.android.phone.PhoneGlobals;
 
 public class ImsUtil {
 
-    private static final String TAG = ImsUtil.class.getSimpleName();
     private static boolean sImsPhoneSupported = false;
 
     private ImsUtil() {
@@ -45,30 +37,4 @@
         return sImsPhoneSupported;
 
     }
-
-    /**
-     * @see MobileNetworkSettings#setIMS
-     * @param context The context to get the content resolver from.
-     * @return Whether IMS is turned on by the user system setting.
-     */
-    static boolean isImsEnabled(Context context) {
-        int value = 0;
-        try {
-            value = android.provider.Settings.Global.getInt(
-                    context.getContentResolver(),
-                    android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED);
-        } catch (SettingNotFoundException e) {
-            return false;
-        }
-
-        switch (value) {
-            case 0:
-                return false;
-            case 1:
-                return true;
-            default:
-                Log.wtf(TAG,"Unexpected value for ENHANCED_4G_MODE_ENABLED: " + value);
-                return false;
-        }
-    }
 }
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 58b8599..b6a4498 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -53,6 +53,7 @@
 import android.util.Log;
 import android.util.Pair;
 
+import com.android.ims.ImsManager;
 import com.android.internal.telephony.CallManager;
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.Connection;
@@ -2084,7 +2085,8 @@
         // enabled video calling, if IMS is disabled we aren't able to support video calling.
         // In the long run, we may instead need to check if there exists a connection service
         // which can support video calling.
-        return mTelephonySharedPreferences.getBoolean(PREF_ENABLE_VIDEO_CALLING, true)
-                && ImsUtil.isImsEnabled(mPhone.getContext());
+        return ImsManager.isVtEnabledByPlatform(mPhone.getContext())
+                && ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())
+                && mTelephonySharedPreferences.getBoolean(PREF_ENABLE_VIDEO_CALLING, true);
     }
 }
diff --git a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
index ba6871c..20fc108 100644
--- a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
+++ b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
@@ -8,12 +8,17 @@
 import android.preference.CheckBoxPreference;
 import android.preference.ListPreference;
 import android.preference.Preference;
+import android.preference.PreferenceCategory;
 import android.preference.PreferenceFragment;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
+import android.telephony.SubInfoRecord;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.util.Log;
 
 import com.android.phone.R;
+import com.android.phone.CallFeaturesSetting;
 import com.android.services.telephony.sip.SipAccountRegistry;
 import com.android.services.telephony.sip.SipSharedPreferences;
 import com.android.services.telephony.sip.SipUtil;
@@ -29,6 +34,9 @@
             new Intent(TelecomManager.ACTION_CONNECTION_SERVICE_CONFIGURE)
                     .addCategory(Intent.CATEGORY_DEFAULT);
 
+    private static final String ACCOUNTS_LIST_CATEGORY_KEY =
+            "phone_accounts_accounts_list_category_key";
+
     private static final String DEFAULT_OUTGOING_ACCOUNT_KEY = "default_outgoing_account";
 
     private static final String CONFIGURE_CALL_ASSISTANT_PREF_KEY =
@@ -48,6 +56,8 @@
     private TelecomManager mTelecomManager;
     private Context mApplicationContext;
 
+    private PreferenceCategory mAccountList;
+
     private AccountSelectionPreference mDefaultOutgoingAccount;
     private AccountSelectionPreference mSelectCallAssistant;
     private Preference mConfigureCallAssistant;
@@ -74,6 +84,16 @@
 
         addPreferencesFromResource(com.android.phone.R.xml.phone_account_settings);
 
+        TelephonyManager telephonyManager =
+                (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE);
+        mAccountList = (PreferenceCategory) getPreferenceScreen().findPreference(
+                ACCOUNTS_LIST_CATEGORY_KEY);
+        if (telephonyManager.getPhoneCount() > 1) {
+            initAccountList();
+        } else {
+            getPreferenceScreen().removePreference(mAccountList);
+        }
+
         mDefaultOutgoingAccount = (AccountSelectionPreference)
                 getPreferenceScreen().findPreference(DEFAULT_OUTGOING_ACCOUNT_KEY);
         if (mTelecomManager.getAllPhoneAccountsCount() > 1) {
@@ -269,4 +289,19 @@
             mConfigureCallAssistant.setEnabled(true);
         }
     }
+
+    private void initAccountList() {
+        List<SubInfoRecord> subscriptions = SubscriptionManager.getActiveSubInfoList();
+        for (int i = 0; i < subscriptions.size(); i++) {
+            String label = subscriptions.get(i).getLabel();
+            Intent intent = new Intent(TelecomManager.ACTION_SHOW_CALL_SETTINGS);
+            intent.putExtra(CallFeaturesSetting.SUB_ID_EXTRA, subscriptions.get(i).subId);
+            intent.putExtra(CallFeaturesSetting.SUB_LABEL_EXTRA, label);
+
+            Preference accountPreference = new Preference(mApplicationContext);
+            accountPreference.setTitle(label);
+            accountPreference.setIntent(intent);
+            mAccountList.addPreference(accountPreference);
+        }
+    }
 }
diff --git a/src/com/android/phone/settings/VoicemailProviderSettings.java b/src/com/android/phone/settings/VoicemailProviderSettings.java
new file mode 100644
index 0000000..fc2e7f8
--- /dev/null
+++ b/src/com/android/phone/settings/VoicemailProviderSettings.java
@@ -0,0 +1,127 @@
+/**
+ * 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.
+ */
+
+package com.android.phone.settings;
+
+import android.telephony.PhoneNumberUtils;
+
+import com.android.internal.telephony.CallForwardInfo;
+import com.android.internal.telephony.CommandsInterface;
+
+/**
+ * Settings for a voicemail provider, including any conditional forwarding information.
+ */
+public class VoicemailProviderSettings {
+
+    // If no forwarding is set, leave the forwarding number unchanged from its current value.
+    public static final CallForwardInfo[] NO_FORWARDING = null;
+
+    /**
+     * Reasons for the forwarding settings we are going to save.
+     */
+    public static final int [] FORWARDING_SETTINGS_REASONS = new int[] {
+        CommandsInterface.CF_REASON_UNCONDITIONAL,
+        CommandsInterface.CF_REASON_BUSY,
+        CommandsInterface.CF_REASON_NO_REPLY,
+        CommandsInterface.CF_REASON_NOT_REACHABLE
+    };
+
+    private String mVoicemailNumber;
+    private CallForwardInfo[] mForwardingSettings;
+
+    /**
+     * Constructs settings object, setting all conditional forwarding to the specified number
+     */
+    public VoicemailProviderSettings(
+            String voicemailNumber, String forwardingNumber, int timeSeconds) {
+        mVoicemailNumber = voicemailNumber;
+        if (forwardingNumber == null || forwardingNumber.length() == 0) {
+            mForwardingSettings = NO_FORWARDING;
+        } else {
+            mForwardingSettings = new CallForwardInfo[FORWARDING_SETTINGS_REASONS.length];
+            for (int i = 0; i < mForwardingSettings.length; i++) {
+                CallForwardInfo fi = new CallForwardInfo();
+                mForwardingSettings[i] = fi;
+                fi.reason = FORWARDING_SETTINGS_REASONS[i];
+                fi.status = (fi.reason == CommandsInterface.CF_REASON_UNCONDITIONAL) ? 0 : 1;
+                fi.serviceClass = CommandsInterface.SERVICE_CLASS_VOICE;
+                fi.toa = PhoneNumberUtils.TOA_International;
+                fi.number = forwardingNumber;
+                fi.timeSeconds = timeSeconds;
+            }
+        }
+    }
+
+    public VoicemailProviderSettings(String voicemailNumber, CallForwardInfo[] infos) {
+        mVoicemailNumber = voicemailNumber;
+        mForwardingSettings = infos;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null) {
+            return false;
+        }
+        if (!(o instanceof VoicemailProviderSettings)) {
+            return false;
+        }
+
+        final VoicemailProviderSettings v = (VoicemailProviderSettings) o;
+        return ((mVoicemailNumber == null && v.getVoicemailNumber() == null)
+                || (mVoicemailNumber != null && mVoicemailNumber.equals(v.getVoicemailNumber()))
+                        && forwardingSettingsEqual(mForwardingSettings, v.getForwardingSettings()));
+    }
+
+    @Override
+    public String toString() {
+        return mVoicemailNumber + ((mForwardingSettings == null) ? ""
+                : ", " + mForwardingSettings.toString());
+    }
+
+    public String getVoicemailNumber() {
+        return mVoicemailNumber;
+    }
+
+    public CallForwardInfo[] getForwardingSettings() {
+        return mForwardingSettings;
+    }
+
+    private boolean forwardingSettingsEqual(CallForwardInfo[] infos1, CallForwardInfo[] infos2) {
+        if (infos1 == infos2) {
+            return true;
+        }
+        if (infos1 == null || infos2 == null) {
+            return false;
+        }
+        if (infos1.length != infos2.length) {
+            return false;
+        }
+
+        for (int i = 0; i < infos1.length; i++) {
+            CallForwardInfo i1 = infos1[i];
+            CallForwardInfo i2 = infos2[i];
+            if (i1.status != i2.status
+                    || i1.reason != i2.reason
+                    || i1.serviceClass != i2.serviceClass
+                    || i1.toa != i2.toa
+                    || i1.number != i2.number
+                    || i1.timeSeconds != i2.timeSeconds) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
diff --git a/src/com/android/phone/settings/VoicemailRingtonePreference.java b/src/com/android/phone/settings/VoicemailRingtonePreference.java
new file mode 100644
index 0000000..3cc48af
--- /dev/null
+++ b/src/com/android/phone/settings/VoicemailRingtonePreference.java
@@ -0,0 +1,65 @@
+package com.android.phone.settings;
+
+import android.content.Context;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.Preference;
+import android.preference.RingtonePreference;
+import android.util.AttributeSet;
+
+import com.android.phone.PhoneGlobals;
+import com.android.phone.common.util.SettingsUtil;
+
+/**
+ * Looks up the voicemail ringtone's name asynchronously and updates the preference's summary when
+ * it is created or updated.
+ */
+public class VoicemailRingtonePreference extends RingtonePreference {
+    private static final int MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY = 1;
+
+    private Runnable mVoicemailRingtoneLookupRunnable;
+    private Handler mVoicemailRingtoneLookupComplete;
+
+    public VoicemailRingtonePreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        mVoicemailRingtoneLookupComplete = new Handler() {
+            @Override
+            public void handleMessage(Message msg) {
+                switch (msg.what) {
+                    case MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY:
+                        setSummary((CharSequence) msg.obj);
+                        break;
+                }
+            }
+        };
+
+        final Preference preference = this;
+        mVoicemailRingtoneLookupRunnable = new Runnable() {
+            @Override
+            public void run() {
+                SettingsUtil.updateRingtoneName(
+                        preference.getContext(),
+                        mVoicemailRingtoneLookupComplete,
+                        RingtoneManager.TYPE_NOTIFICATION,
+                        preference,
+                        MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY);
+            }
+        };
+
+        updateRingtoneName();
+    }
+
+    @Override
+    protected void onSaveRingtone(Uri ringtoneUri) {
+        super.onSaveRingtone(ringtoneUri);
+        updateRingtoneName();
+    }
+
+    private void updateRingtoneName() {
+        new Thread(mVoicemailRingtoneLookupRunnable).start();
+    }
+}
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 5a480a5..f50db0c 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
@@ -35,7 +36,6 @@
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.PhoneProxy;
-import com.android.internal.telephony.SubscriptionController;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.phone.R;
 
@@ -123,8 +123,10 @@
                 if (record != null) {
                     subDisplayName = record.displayName;
                     slotId = record.slotId;
+
                     // Assign a "fake" color while the underlying Telephony stuff is refactored
-                    color = makeFakeColor(subId);
+                    // Assign PhoneAccount.NO_COLOR to first slot so single-SIM phones are unchanged
+                    color = slotId == 0? PhoneAccount.NO_COLOR : makeFakeColor(subId);
                 }
 
                 String slotIdString;
@@ -158,7 +160,9 @@
                     .setSubscriptionAddress(
                             Uri.fromParts(PhoneAccount.SCHEME_TEL, subNumber, null))
                     .setCapabilities(capabilities)
-                    .setIconResId(getPhoneAccountIcon(slotId))
+                    .setIconBitmap(BitmapFactory.decodeResource(
+                            mContext.getResources(),
+                            getPhoneAccountIcon(slotId)))
                     .setColor(color)
                     .setShortDescription(description)
                     .setSupportedUriSchemes(Arrays.asList(