Merge "Overlay swap capability after merge" 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 b7f2d55..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;
@@ -57,6 +56,7 @@
 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;
@@ -114,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
@@ -123,10 +130,6 @@
     // 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";
 
     // Suffix appended to provider key for storing vm number
     public static final String VM_NUMBER_TAG = "#VMNumber";
@@ -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 {
@@ -499,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;
@@ -810,7 +817,7 @@
             mNewFwdSettings = VoicemailProviderSettings.NO_FORWARDING;
         }
 
-        //Throw a warning if the voicemail is the same and we did not change forwarding.
+        // 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);
@@ -1415,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) &&
@@ -1470,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);
@@ -1482,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)) {
@@ -1573,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());
@@ -1597,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
@@ -1628,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();
@@ -1848,9 +1825,6 @@
      */
     private void maybeSaveSettingsForVoicemailProvider(String key,
             VoicemailProviderSettings newSettings) {
-        if (mVoicemailProviders == null) {
-            return;
-        }
         final VoicemailProviderSettings curSettings = loadSettingsForVoiceMailProvider(key);
         if (newSettings.equals(curSettings)) {
             if (DBG) {
@@ -1929,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/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/ConferenceParticipantConnection.java b/src/com/android/services/telephony/ConferenceParticipantConnection.java
new file mode 100644
index 0000000..a1ed6a3
--- /dev/null
+++ b/src/com/android/services/telephony/ConferenceParticipantConnection.java
@@ -0,0 +1,97 @@
+/*
+ * 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.services.telephony;
+
+import com.android.internal.telephony.PhoneConstants;
+
+import android.net.Uri;
+import android.telecom.ConferenceParticipant;
+import android.telecom.Connection;
+import android.telecom.DisconnectCause;
+import android.telecom.PhoneCapabilities;
+
+/**
+ * Represents a participant in a conference call.
+ */
+public class ConferenceParticipantConnection extends Connection {
+
+    /**
+     * The endpoint URI For the conference participant.
+     */
+    private final Uri mEndpoint;
+
+    /**
+     * The connection which owns this participant.
+     */
+    private final Connection mParentConnection;
+
+    /**
+     * Creates a new instance.
+     *
+     * @param participant The conference participant to create the instance for.
+     */
+    public ConferenceParticipantConnection(
+            Connection parentConnection, ConferenceParticipant participant) {
+
+        mParentConnection = parentConnection;
+        setAddress(participant.getHandle(), PhoneConstants.PRESENTATION_ALLOWED);
+        setCallerDisplayName(participant.getDisplayName(), PhoneConstants.PRESENTATION_ALLOWED);
+        updateState(participant.getState());
+        mEndpoint = participant.getEndpoint();
+        setCapabilities();
+    }
+
+    /**
+     * Changes the state of the conference participant.
+     *
+     * @param newState The new state.
+     */
+    public void updateState(int newState) {
+        switch (newState) {
+            case STATE_INITIALIZING:
+                setInitializing();
+                break;
+            case STATE_RINGING:
+                setRinging();
+                break;
+            case STATE_DIALING:
+                setDialing();
+                break;
+            case STATE_HOLDING:
+                setOnHold();
+                break;
+            case STATE_ACTIVE:
+                setActive();
+                break;
+            case STATE_DISCONNECTED:
+                setDisconnected(new DisconnectCause(DisconnectCause.REMOTE));
+                break;
+            default:
+                setActive();
+        }
+    }
+
+    /**
+     * Configures the {@link android.telecom.PhoneCapabilities} applicable to this connection.  A
+     * conference participant can only be disconnected from a conference since there is not
+     * actual connection to the participant which could be split from the conference.
+     */
+    private void setCapabilities() {
+        int capabilities = PhoneCapabilities.DISCONNECT_FROM_CONFERENCE;
+        setCallCapabilities(capabilities);
+    }
+}
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(
diff --git a/src/com/android/services/telephony/TelephonyConferenceController.java b/src/com/android/services/telephony/TelephonyConferenceController.java
index 5786b25..b64464d 100644
--- a/src/com/android/services/telephony/TelephonyConferenceController.java
+++ b/src/com/android/services/telephony/TelephonyConferenceController.java
@@ -18,11 +18,14 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
+import android.net.Uri;
 import android.telecom.Conference;
+import android.telecom.ConferenceParticipant;
 import android.telecom.Connection;
 import android.telecom.DisconnectCause;
 
@@ -53,11 +56,31 @@
         public void onDestroyed(Connection connection) {
             remove((TelephonyConnection) connection);
         }
+
+        /**
+         * Handles notifications from an connection that a participant in a conference has changed
+         * state.
+         *
+         * @param c The connection.
+         * @param participant The participant information.
+         */
+        @Override
+        public void onConferenceParticipantChanged(Connection c, ConferenceParticipant participant)
+        {
+            Log.v(this, "onConferenceParticipantChanged: %s", participant);
+            handleConferenceParticipantUpdate(c, participant);
+        }
     };
 
     /** The known connections. */
     private final List<TelephonyConnection> mTelephonyConnections = new ArrayList<>();
 
+    /**
+     * The known conference participant connections.  The HashMap is keyed by endpoint Uri.
+     */
+    private final HashMap<Uri, ConferenceParticipantConnection> mConferenceParticipantConnections =
+            new HashMap<>();
+
     private final TelephonyConnectionService mConnectionService;
 
     public TelephonyConferenceController(TelephonyConnectionService connectionService) {
@@ -218,4 +241,44 @@
             }
         }
     }
+
+    /**
+     * Handles state changes for a conference participant.
+     *
+     * @param parent The connection which was notified of the conference participant.
+     * @param participant The conference participant.
+     */
+    private void handleConferenceParticipantUpdate(
+            Connection parent, ConferenceParticipant participant) {
+
+        Uri endpoint = participant.getEndpoint();
+        if (!mConferenceParticipantConnections.containsKey(endpoint)) {
+            createConferenceParticipantConnection(parent, participant);
+        } else {
+            ConferenceParticipantConnection connection =
+                    mConferenceParticipantConnections.get(endpoint);
+            connection.updateState(participant.getState());
+        }
+    }
+
+    /**
+     * Creates a new {@link ConferenceParticipantConnection} to represent a
+     * {@link ConferenceParticipant}.
+     * <p>
+     * The new connection is added to the conference controller and connection service.
+     *
+     * @param parent The connection which was notified of the participant change (e.g. the
+     *                         parent connection).
+     * @param participant The conference participant information.
+     */
+    private void createConferenceParticipantConnection(
+            Connection parent, ConferenceParticipant participant) {
+
+        ConferenceParticipantConnection connection = new ConferenceParticipantConnection(
+                parent, participant);
+        connection.addConnectionListener(mConnectionListener);
+        mConferenceParticipantConnections.put(participant.getEndpoint(), connection);
+
+        // TODO: Inform telecom of the new participant.
+    }
 }
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index b8d3142..3af7481 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -22,6 +22,7 @@
 import android.os.Message;
 import android.telecom.AudioState;
 import android.telecom.Conference;
+import android.telecom.ConferenceParticipant;
 import android.telecom.Connection;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneCapabilities;
@@ -140,6 +141,17 @@
         public void onAudioQualityChanged(int audioQuality) {
             setAudioQuality(audioQuality);
         }
+
+        /**
+         * Handles a change in the state of a conference participant, as reported by the
+         * {@link com.android.internal.telephony.Connection}.
+         *
+         * @param participant The participant which changed.
+         */
+        @Override
+        public void onConferenceParticipantChanged(ConferenceParticipant participant) {
+            updateConferenceParticipant(participant);
+        }
     };
 
     private com.android.internal.telephony.Connection mOriginalConnection;