Allowing enable/disable of phone accounts. (3/3)

Phone Accounts:
- Added Phone account enable/disable activity, accessible from the
"Make calls via" preference screen.
- Changed Telephony PhoneAccount registration so that it first updates
existing PhoneAccounts (ensuring enable/disable setting retained), and
then removes any that no longer exist.

SIP:
Removed the "primary profile" SIP setting in favour of being able to
enabled and disable the associated PhoneAccounts.
Added migration to automatically enable the previous "primary profile".

Bug: 17306514
Bug: 17408536
Change-Id: I696e3382730ea7bb40d680798bcab965517c438b
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index 88de152..bb23292 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -465,6 +465,11 @@
      */
     private boolean mReadingSettingsForDefaultProvider = false;
 
+    /**
+     * Used to indicate that the voicemail preference should be shown.
+     */
+    private boolean mShowVoicemailPreference = false;
+
     /*
      * Click Listeners, handle click based on objects attached to UI.
      */
@@ -603,6 +608,22 @@
         return false;
     }
 
+    /**
+     * Called just prior to showing an AccountSelection dialog to re-populate the model of the
+     * AccountSelection dialog.  Important to ensure changes to the enabled state of
+     * {@code PhoneAccount}s are reflected in the dialog.
+     *
+     * @param pref The account selection preference dialog being shown.
+     */
+    @Override
+    public void onAccountSelectionDialogShow(AccountSelectionPreference pref) {
+        if (pref == mDefaultOutgoingAccount) {
+            populateDefaultOutgoingAccountsModel();
+        } else if (pref == mSimCallManagerAccount) {
+            populateSimCallManagerAccountsModel();
+        }
+    }
+
     @Override
     public void onDialogClosed(EditPhoneNumberPreference preference, int buttonClicked) {
         if (DBG) log("onPreferenceClick: request preference click on dialog close: " +
@@ -1509,13 +1530,121 @@
         super.onCreate(icicle);
         if (DBG) log("onCreate(). Intent: " + getIntent());
         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);
+                }
+            }
+        };
+
+        ActionBar actionBar = getActionBar();
+        if (actionBar != null) {
+            // android.R.id.home will be triggered in onOptionsItemSelected()
+            actionBar.setDisplayShowHomeEnabled(true);
+            actionBar.setDisplayHomeAsUpEnabled(true);
+            actionBar.setDisplayShowTitleEnabled(true);
+        }
+
+        // Show the voicemail preference in onResume if the calling intent specifies the
+        // ACTION_ADD_VOICEMAIL action.
+        mShowVoicemailPreference = (icicle == null) &&
+                getIntent().getAction().equals(ACTION_ADD_VOICEMAIL);
+    }
+
+    private void initPhoneAccountPreferences() {
+        mDefaultOutgoingAccount = (AccountSelectionPreference)
+                findPreference(DEFAULT_OUTGOING_ACCOUNT_KEY);
+        mSimCallManagerAccount = (AccountSelectionPreference)
+                findPreference(WIFI_CALL_MANAGER_ACCOUNT_KEY);
+
+        TelecommManager telecommManager = TelecommManager.from(this);
+
+        int allPhoneAccountsCount = telecommManager.getAllPhoneAccountsCount();
+        // Show the phone accounts preference if there are is more than one phone account (this
+        // includes disabled phone accounts).  The default selection, however, only includes those
+        // PhoneAccounts which are enabled.
+        if (allPhoneAccountsCount > 1) {
+            populateDefaultOutgoingAccountsModel();
+
+            mDefaultOutgoingAccount.setListener(this);
+        } else {
+            getPreferenceScreen().removePreference(mDefaultOutgoingAccount);
+        }
+
+        List<PhoneAccountHandle> simCallManagers = telecommManager.getSimCallManagers();
+        if (!simCallManagers.isEmpty()) {
+            populateSimCallManagerAccountsModel();
+            mSimCallManagerAccount.setListener(this);
+        } else {
+            getPreferenceScreen().removePreference(mSimCallManagerAccount);
+        }
+    }
+
+    private void createSipCallSettings() {
+        // Add Internet call settings.
+        if (SipUtil.isVoipSupported(this)) {
+            mSipManager = SipManager.newInstance(this);
+            mSipSharedPreferences = new SipSharedPreferences(this);
+            addPreferencesFromResource(
+                    com.android.services.telephony.sip.R.xml.sip_settings_category);
+            mButtonSipCallOptions = getSipCallOptionPreference();
+            mButtonSipCallOptions.setOnPreferenceChangeListener(this);
+            mButtonSipCallOptions.setValueIndex(
+                    mButtonSipCallOptions.findIndexOfValue(
+                            mSipSharedPreferences.getSipCallOption()));
+            mButtonSipCallOptions.setSummary(mButtonSipCallOptions.getEntry());
+        }
+    }
+
+    private boolean canLaunchIntent(Intent intent) {
+        PackageManager pm = getPackageManager();
+        return pm.resolveActivity(intent, PackageManager.GET_ACTIVITIES) != null;
+    }
+
+    // Gets the call options for SIP depending on whether SIP is allowed only
+    // on Wi-Fi only; also make the other options preference invisible.
+    private ListPreference getSipCallOptionPreference() {
+        ListPreference wifiAnd3G = (ListPreference)
+                findPreference(BUTTON_SIP_CALL_OPTIONS);
+        ListPreference wifiOnly = (ListPreference)
+                findPreference(BUTTON_SIP_CALL_OPTIONS_WIFI_ONLY);
+        PreferenceScreen sipSettings = (PreferenceScreen)
+                getPreferenceScreen().findPreference(SIP_SETTINGS_PREFERENCE_SCREEN_KEY);
+        if (SipManager.isSipWifiOnly(this)) {
+            sipSettings.removePreference(wifiAnd3G);
+            return wifiOnly;
+        } else {
+            sipSettings.removePreference(wifiOnly);
+            return wifiAnd3G;
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mForeground = true;
+
+        PreferenceScreen preferenceScreen = getPreferenceScreen();
+        if (preferenceScreen != null) {
+            preferenceScreen.removeAll();
+        }
 
         addPreferencesFromResource(R.xml.call_feature_setting);
-
         initPhoneAccountPreferences();
 
-        mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
-
         // get buttons
         PreferenceScreen prefSet = getPreferenceScreen();
         mSubMenuVoicemailSettings = (EditPhoneNumberPreference)findPreference(BUTTON_VOICEMAIL_KEY);
@@ -1541,7 +1670,6 @@
             initVoiceMailProviders();
         }
 
-        final ContentResolver contentResolver = getContentResolver();
 
         if (mButtonDTMF != null) {
             if (getResources().getBoolean(R.bool.dtmf_type_enabled)) {
@@ -1609,134 +1737,29 @@
             }
         }
 
-        // create intent to bring up contact list
-        mContactListIntent = new Intent(Intent.ACTION_GET_CONTENT);
-        mContactListIntent.setType(android.provider.Contacts.Phones.CONTENT_ITEM_TYPE);
-
         // check the intent that started this activity and pop up the voicemail
         // dialog if we've been asked to.
         // 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 (icicle == null) {
-            if (getIntent().getAction().equals(ACTION_ADD_VOICEMAIL) &&
-                    mVoicemailProviders != null) {
-                if (DBG) {
-                    log("ACTION_ADD_VOICEMAIL Intent is thrown. current VM data size: "
-                            + mVMProvidersData.size());
-                }
-                if (mVMProvidersData.size() > 1) {
-                    simulatePreferenceClick(mVoicemailProviders);
-                } else {
-                    onPreferenceChange(mVoicemailProviders, DEFAULT_VM_PROVIDER_KEY);
-                    mVoicemailProviders.setValue(DEFAULT_VM_PROVIDER_KEY);
-                }
+        if (mShowVoicemailPreference && mVoicemailProviders != null) {
+            if (DBG) {
+                log("ACTION_ADD_VOICEMAIL Intent is thrown. current VM data size: "
+                        + mVMProvidersData.size());
             }
+            if (mVMProvidersData.size() > 1) {
+                simulatePreferenceClick(mVoicemailProviders);
+            } else {
+                onPreferenceChange(mVoicemailProviders, DEFAULT_VM_PROVIDER_KEY);
+                mVoicemailProviders.setValue(DEFAULT_VM_PROVIDER_KEY);
+            }
+            mShowVoicemailPreference = false;
         }
+
         updateVoiceNumberField();
         mVMProviderSettingsForced = false;
         createSipCallSettings();
 
-        mVoicemailRingtoneLookupRunnable = new Runnable() {
-            @Override
-            public void run() {
-                if (mVoicemailNotificationRingtone != null) {
-                    SettingsUtil.updateRingtoneName(
-                            mPhone.getContext(),
-                            mVoicemailRingtoneLookupComplete,
-                            RingtoneManager.TYPE_NOTIFICATION,
-                            mVoicemailNotificationRingtone,
-                            MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY);
-                }
-            }
-        };
-
-        ActionBar actionBar = getActionBar();
-        if (actionBar != null) {
-            // android.R.id.home will be triggered in onOptionsItemSelected()
-            actionBar.setDisplayShowHomeEnabled(true);
-            actionBar.setDisplayHomeAsUpEnabled(true);
-            actionBar.setDisplayShowTitleEnabled(true);
-        }
-    }
-
-    private void initPhoneAccountPreferences() {
-        mDefaultOutgoingAccount = (AccountSelectionPreference)
-                findPreference(DEFAULT_OUTGOING_ACCOUNT_KEY);
-        mSimCallManagerAccount = (AccountSelectionPreference)
-                findPreference(WIFI_CALL_MANAGER_ACCOUNT_KEY);
-
-        TelecommManager telecommManager = TelecommManager.from(this);
-
-        List<PhoneAccountHandle> enabledPhoneAccounts = telecommManager.getEnabledPhoneAccounts();
-        if (enabledPhoneAccounts.size() > 1) {
-            mDefaultOutgoingAccount.setModel(
-                    telecommManager,
-                    enabledPhoneAccounts,
-                    telecommManager.getUserSelectedOutgoingPhoneAccount(),
-                    getString(R.string.phone_accounts_ask_every_time));
-            mDefaultOutgoingAccount.setListener(this);
-        } else {
-            getPreferenceScreen().removePreference(mDefaultOutgoingAccount);
-        }
-
-        List<PhoneAccountHandle> simCallManagers = telecommManager.getSimCallManagers();
-        if (!simCallManagers.isEmpty()) {
-            mSimCallManagerAccount.setModel(
-                    telecommManager,
-                    simCallManagers,
-                    telecommManager.getSimCallManager(),
-                    getString(R.string.wifi_calling_do_not_use));
-            mSimCallManagerAccount.setListener(this);
-        } else {
-            getPreferenceScreen().removePreference(mSimCallManagerAccount);
-        }
-    }
-
-    private void createSipCallSettings() {
-        // Add Internet call settings.
-        if (SipUtil.isVoipSupported(this)) {
-            mSipManager = SipManager.newInstance(this);
-            mSipSharedPreferences = new SipSharedPreferences(this);
-            addPreferencesFromResource(
-                    com.android.services.telephony.sip.R.xml.sip_settings_category);
-            mButtonSipCallOptions = getSipCallOptionPreference();
-            mButtonSipCallOptions.setOnPreferenceChangeListener(this);
-            mButtonSipCallOptions.setValueIndex(
-                    mButtonSipCallOptions.findIndexOfValue(
-                            mSipSharedPreferences.getSipCallOption()));
-            mButtonSipCallOptions.setSummary(mButtonSipCallOptions.getEntry());
-        }
-    }
-
-    private boolean canLaunchIntent(Intent intent) {
-        PackageManager pm = getPackageManager();
-        return pm.resolveActivity(intent, PackageManager.GET_ACTIVITIES) != null;
-    }
-
-    // Gets the call options for SIP depending on whether SIP is allowed only
-    // on Wi-Fi only; also make the other options preference invisible.
-    private ListPreference getSipCallOptionPreference() {
-        ListPreference wifiAnd3G = (ListPreference)
-                findPreference(BUTTON_SIP_CALL_OPTIONS);
-        ListPreference wifiOnly = (ListPreference)
-                findPreference(BUTTON_SIP_CALL_OPTIONS_WIFI_ONLY);
-        PreferenceScreen sipSettings = (PreferenceScreen)
-                getPreferenceScreen().findPreference(SIP_SETTINGS_PREFERENCE_SCREEN_KEY);
-        if (SipManager.isSipWifiOnly(this)) {
-            sipSettings.removePreference(wifiAnd3G);
-            return wifiOnly;
-        } else {
-            sipSettings.removePreference(wifiOnly);
-            return wifiAnd3G;
-        }
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        mForeground = true;
-
         if (isAirplaneModeOn()) {
             Preference sipSettings = findPreference(SIP_SETTINGS_PREFERENCE_SCREEN_KEY);
             PreferenceScreen screen = getPreferenceScreen();
@@ -2117,6 +2140,41 @@
     }
 
     /**
+     * Populates the phone accounts which could potentially be selected as the default.
+     */
+    private void populateDefaultOutgoingAccountsModel() {
+        if (mDefaultOutgoingAccount == null ) {
+            return;
+        }
+
+        TelecommManager telecommManager = TelecommManager.from(this);
+        List<PhoneAccountHandle> enabledPhoneAccounts = telecommManager.getEnabledPhoneAccounts();
+        mDefaultOutgoingAccount.setModel(
+                telecommManager,
+                enabledPhoneAccounts,
+                telecommManager.getUserSelectedOutgoingPhoneAccount(),
+                getString(R.string.phone_accounts_ask_every_time));
+    }
+
+    /**
+     * Populates the phone accounts which could potentially be selected as the default sim call
+     * manager.
+     */
+    private void populateSimCallManagerAccountsModel() {
+        if (mSimCallManagerAccount == null) {
+            return;
+        }
+
+        TelecommManager telecommManager = TelecommManager.from(this);
+        List<PhoneAccountHandle> simCallManagers = telecommManager.getSimCallManagers();
+        mSimCallManagerAccount.setModel(
+                telecommManager,
+                simCallManagers,
+                telecommManager.getSimCallManager(),
+                getString(R.string.wifi_calling_do_not_use));
+    }
+
+    /**
      * Deletes settings for the specified provider.
      */
     private void deleteSettingsForVoicemailProvider(String key) {
diff --git a/src/com/android/phone/settings/AccountSelectionPreference.java b/src/com/android/phone/settings/AccountSelectionPreference.java
index 32149ae..8469a18 100644
--- a/src/com/android/phone/settings/AccountSelectionPreference.java
+++ b/src/com/android/phone/settings/AccountSelectionPreference.java
@@ -16,7 +16,13 @@
 
 package com.android.phone.settings;
 
+import com.android.phone.R;
+
+import android.app.AlertDialog;
 import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.UserHandle;
 import android.preference.ListPreference;
 import android.preference.Preference;
 import android.telecomm.PhoneAccountHandle;
@@ -31,8 +37,10 @@
 
     public interface AccountSelectionListener {
         boolean onAccountSelected(AccountSelectionPreference pref, PhoneAccountHandle account);
+        void onAccountSelectionDialogShow(AccountSelectionPreference pref);
     }
 
+    private final Context mContext;
     private AccountSelectionListener mListener;
     private PhoneAccountHandle[] mAccounts;
     private String[] mEntryValues;
@@ -40,11 +48,13 @@
 
     public AccountSelectionPreference(Context context) {
         super(context);
+        mContext = context;
         setOnPreferenceChangeListener(this);
     }
 
     public AccountSelectionPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mContext = context;
         setOnPreferenceChangeListener(this);
     }
 
@@ -93,4 +103,39 @@
         }
         return false;
     }
+
+    /**
+     * Modifies the dialog to change the default "Cancel" button to "Choose Accounts", which
+     * triggers the {@link PhoneAccountSelectionPreferenceActivity} to be shown.
+     *
+     * @param builder The {@code AlertDialog.Builder}.
+     */
+    @Override
+    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+        // Notify the listener that the dialog is about to be built.  This is important so that the
+        // list of enabled accounts can be updated prior to showing the dialog.
+        mListener.onAccountSelectionDialogShow(this);
+
+        final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int whichButton) {
+                showSelectPhoneAccounts();
+            }
+        };
+        builder.setNegativeButton(R.string.phone_accounts_choose_accounts, listener);
+        super.onPrepareDialogBuilder(builder);
+    }
+
+    /**
+     * Displays the {@link PhoneAccountSelectionPreferenceActivity} where the user is able to
+     * enable and disable phone accounts.
+     */
+    private void showSelectPhoneAccounts() {
+        Intent intent = new Intent(mContext, PhoneAccountSelectionPreferenceActivity.class);
+        intent.setAction(Intent.ACTION_MAIN);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        mContext.startActivityAsUser(intent, null, UserHandle.CURRENT);
+    }
 }
diff --git a/src/com/android/phone/settings/PhoneAccountSelectionPreferenceActivity.java b/src/com/android/phone/settings/PhoneAccountSelectionPreferenceActivity.java
new file mode 100644
index 0000000..7dd1190
--- /dev/null
+++ b/src/com/android/phone/settings/PhoneAccountSelectionPreferenceActivity.java
@@ -0,0 +1,171 @@
+/*
+ * 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.app.ActionBar;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceFragment;
+import android.preference.SwitchPreference;
+import android.telecomm.PhoneAccount;
+import android.telecomm.PhoneAccountHandle;
+import android.telecomm.TelecommManager;
+
+import com.android.internal.util.CharSequences;
+import com.android.phone.R;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Preference activity used to facilitate enabling and disabling phone accounts by the user.
+ */
+public class PhoneAccountSelectionPreferenceActivity extends PreferenceActivity {
+
+    /**
+     * Preference fragment containing a list of all {@link PhoneAccount}s in the form of switches
+     * the user can use to enable or disable accounts.
+     */
+    public static class PhoneAccountSelectionPreferenceFragment extends PreferenceFragment
+            implements Preference.OnPreferenceChangeListener {
+        private static final String CATEGORY_PHONE_ACCOUNTS_KEY = "phone_accounts_list";
+
+        private TelecommManager mTelecommManager;
+        private PreferenceCategory mPhoneAccountsCategory;
+
+        /**
+         * Represents a single {@link PhoneAccount} for the purpose enabling and disabling.
+         */
+        static class PhoneAccountPreference extends SwitchPreference {
+            private PhoneAccountHandle mPhoneAccountHandle;
+            private boolean mPreviousState;
+
+            public PhoneAccountPreference(Context context, PhoneAccount phoneAccount) {
+                super(context);
+
+                setPhoneAccount(phoneAccount);
+            }
+
+            /**
+             * Configures the {@code PhoneAccountPreference} for the passed in {@link PhoneAccount}.
+             *
+             * @param phoneAccount The phone account.
+             */
+            private void setPhoneAccount(PhoneAccount phoneAccount) {
+                mPhoneAccountHandle = phoneAccount.getAccountHandle();
+                mPreviousState = phoneAccount.isEnabled();
+                this.setTitle(phoneAccount.getLabel());
+                this.setChecked(mPreviousState);
+            }
+
+            public boolean getPreviousState() {
+                return mPreviousState;
+            }
+
+            public PhoneAccountHandle getPhoneAccountHandle() {
+                return mPhoneAccountHandle;
+            }
+        }
+
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+
+            addPreferencesFromResource(R.xml.phone_account_selection);
+            mPhoneAccountsCategory = (PreferenceCategory) findPreference(
+                    CATEGORY_PHONE_ACCOUNTS_KEY);
+            mTelecommManager = TelecommManager.from(this.getActivity());
+
+            List<PhoneAccount> phoneAccounts = mTelecommManager.getAllPhoneAccounts();
+            Collections.sort(phoneAccounts, new Comparator<PhoneAccount>() {
+                @Override
+                public int compare(PhoneAccount o1, PhoneAccount o2) {
+                    return CharSequences.compareToIgnoreCase(o1.getLabel(), o2.getLabel());
+                }
+            });
+
+            for (PhoneAccount phoneAccount : phoneAccounts) {
+                // Do not add Sim PhoneAccounts.
+                if (phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
+                    continue;
+                }
+
+                PhoneAccountPreference phoneAccountPreference = new PhoneAccountPreference(
+                        getActivity(), phoneAccount);
+                phoneAccountPreference.setOnPreferenceChangeListener(this);
+                phoneAccountPreference.setEnabled(!phoneAccount.hasCapabilities(
+                        PhoneAccount.CAPABILITY_ALWAYS_ENABLED));
+                mPhoneAccountsCategory.addPreference(phoneAccountPreference);
+            }
+        }
+
+        /**
+         * Handles changes to preferences
+         * @param preference The preference which changed.
+         * @param newValue The new value of the preference.
+         * @return
+         */
+        @Override
+        public boolean onPreferenceChange(Preference preference, Object newValue) {
+            if (preference instanceof PhoneAccountPreference) {
+                PhoneAccountPreference phoneAccountPreference = (PhoneAccountPreference) preference;
+                boolean newState = Boolean.valueOf(newValue.toString()).booleanValue();
+
+                if (newState != phoneAccountPreference.getPreviousState()) {
+                    mTelecommManager.setPhoneAccountEnabled(
+                            phoneAccountPreference.getPhoneAccountHandle(), newState);
+                }
+                return true;
+            }
+            return false;
+        }
+    }
+
+    @Override
+    public void onBuildHeaders(List<Header> target) {
+        loadHeadersFromResource(R.xml.phone_account_selection_activity, target);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        setTitle(getResources().getString(R.string.call_settings));
+        ActionBar actionBar = getActionBar();
+        if (actionBar != null) {
+            actionBar.setDisplayShowHomeEnabled(false);
+            actionBar.setDisplayHomeAsUpEnabled(false);
+        }
+
+        // By default, show the main fragment.
+        Intent intent = getIntent();
+        if (intent.getStringArrayExtra(EXTRA_SHOW_FRAGMENT) == null) {
+            getIntent().putExtra(EXTRA_SHOW_FRAGMENT,
+                    PhoneAccountSelectionPreferenceFragment.class.getName());
+        }
+
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public boolean isValidFragment(String fragmentName) {
+        return true;
+    }
+}
diff --git a/src/com/android/services/telephony/TelecommAccountRegistry.java b/src/com/android/services/telephony/TelecommAccountRegistry.java
index 749739a..7ec2c4e 100644
--- a/src/com/android/services/telephony/TelecommAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecommAccountRegistry.java
@@ -45,6 +45,8 @@
  * removal of SIMs and SIP accounts.
  */
 final class TelecommAccountRegistry {
+    private static final boolean DBG = false; /* STOP SHIP if true */
+
     private final static int[] phoneAccountIcons = {
             R.drawable.ic_multi_sim,
             R.drawable.ic_multi_sim1,
@@ -67,7 +69,6 @@
         }
 
         void teardown() {
-            mTelecommManager.unregisterPhoneAccount(mAccount.getAccountHandle());
             mIncomingCallNotifier.teardown();
         }
 
@@ -117,22 +118,37 @@
                     dummyPrefix + mContext.getResources().getString(
                             R.string.sim_description_default, slotId);
 
+            // By default all SIM phone accounts can place emergency calls.
+            int capabilities = PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
+                    PhoneAccount.CAPABILITY_CALL_PROVIDER |
+                    PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS;
+
+            // Indicate the emergency calling PhoneAccount is ALWAYS enabled.  This capability is
+            // important to ensure the emergency-only PhoneAccount cannot be disabled.
+            if (isEmergency) {
+                capabilities |= PhoneAccount.CAPABILITY_ALWAYS_ENABLED;
+            }
+
             PhoneAccount account = PhoneAccount.builder(phoneAccountHandle, label)
                     .setAddress(Uri.fromParts(PhoneAccount.SCHEME_TEL, line1Number, null))
                     .setSubscriptionAddress(
                             Uri.fromParts(PhoneAccount.SCHEME_TEL, subNumber, null))
-                    .setCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
-                            PhoneAccount.CAPABILITY_CALL_PROVIDER)
+                    .setCapabilities(capabilities)
                     .setIconResId(getPhoneAccountIcon(slotId))
                     .setShortDescription(description)
                     .setSupportedUriSchemes(Arrays.asList(
                             PhoneAccount.SCHEME_TEL, PhoneAccount.SCHEME_VOICEMAIL))
+                    .setEnabled(true)
                     .build();
 
             // Register with Telecomm and put into the account entry.
             mTelecommManager.registerPhoneAccount(account);
             return account;
         }
+
+        public PhoneAccountHandle getPhoneAccountHandle() {
+            return mAccount != null ? mAccount.getAccountHandle() : null;
+        }
     }
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -190,7 +206,6 @@
         intentFilter.addAction(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED);
         intentFilter.addAction(TelephonyIntents.ACTION_SUBINFO_CONTENT_CHANGE);
         mContext.registerReceiver(mReceiver, intentFilter);
-        setupAccounts();
     }
 
     static PhoneAccountHandle makePstnPhoneAccountHandle(Phone phone) {
@@ -207,22 +222,43 @@
         return new PhoneAccountHandle(pstnConnectionServiceName, id);
     }
 
-    private void clearCurrentTelephonyAccounts() {
+    /**
+     * Determines if the list of {@link AccountEntry}(s) contains an {@link AccountEntry} with a
+     * specified {@link PhoneAccountHandle}.
+     *
+     * @param handle The {@link PhoneAccountHandle}.
+     * @return {@code True} if an entry exists.
+     */
+    private boolean hasAccountEntryForPhoneAccount(PhoneAccountHandle handle) {
+        for (AccountEntry entry : mAccounts) {
+            if (entry.getPhoneAccountHandle().equals(handle)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Un-registers any {@link PhoneAccount}s which are no longer present in the list
+     * {@code AccountEntry}(s).
+     */
+    private void cleanupPhoneAccounts() {
         ComponentName telephonyComponentName =
                 new ComponentName(mContext, TelephonyConnectionService.class);
-        List<PhoneAccountHandle> accountHandles = mTelecommManager.getEnabledPhoneAccounts();
+
+        List<PhoneAccountHandle> accountHandles = mTelecommManager.getAllPhoneAccountHandles();
         for (PhoneAccountHandle handle : accountHandles) {
-            if (telephonyComponentName.equals(handle.getComponentName())) {
+            if (telephonyComponentName.equals(handle.getComponentName()) &&
+                    !hasAccountEntryForPhoneAccount(handle)) {
+                Log.d(this, "Unregistering phone account %s.", handle);
                 mTelecommManager.unregisterPhoneAccount(handle);
             }
         }
     }
 
     private void setupAccounts() {
-        // Before we do anything, we need to clear whatever entries we registered at boot.
-        clearCurrentTelephonyAccounts();
-
-        // Go through SIM-based phones and register ourselves
+        // Go through SIM-based phones and register ourselves -- registering an existing account
+        // will cause the existing entry to be replaced.
         Phone[] phones = PhoneFactory.getPhones();
         Log.d(this, "Found %d phones.  Attempting to register.", phones.length);
         for (Phone phone : phones) {
@@ -242,9 +278,12 @@
         }
 
         // Add a fake account entry.
-        if (phones.length > 0 && "TRUE".equals(System.getProperty("dummy_sim"))) {
+        if ( DBG && phones.length > 0 && "TRUE".equals(System.getProperty("dummy_sim"))) {
             mAccounts.add(new AccountEntry(phones[0], false /* emergency */, true /* isDummy */));
         }
+
+        // Clean up any PhoneAccounts that are no longer relevant
+        cleanupPhoneAccounts();
     }
 
     private int getPhoneAccountIcon(int index) {