Merge "Request the new MAC address permission to show the MAC address in the UI" into mnc-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e707c4e..e6e3cd9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -151,6 +151,12 @@
     <string name="phone_accounts_add_sip_account">Add SIP account</string>
     <!-- Description label for icon to configure a phone account's settings. -->
     <string name="phone_accounts_configure_account_settings">Configure account settings</string>
+    <!-- Label for heading that takes user to the list of calling accounts where they can enable
+         and disable all accounts. -->
+    <string name="phone_accounts_all_calling_accounts">All calling accounts</string>
+    <!-- Summary for all-calling-account setting indicating that is where the user goes to enable
+         and disable phone accounts. -->
+    <string name="phone_accounts_all_calling_accounts_summary">Enable active calling accounts</string>
 
     <!-- Title for setting to select Wi-Fi call manager account -->
     <string name="wifi_calling">Wi-Fi calling</string>
diff --git a/res/xml/phone_account_settings.xml b/res/xml/phone_account_settings.xml
index 119accd..82e7a87 100644
--- a/res/xml/phone_account_settings.xml
+++ b/res/xml/phone_account_settings.xml
@@ -26,7 +26,19 @@
             android:key="default_outgoing_account"
             android:title="@string/phone_accounts_make_calls_with"
             android:defaultValue=""
-            android:persistent="false" />
+            android:persistent="false"
+            android:order="1" />
+
+    <PreferenceScreen
+        android:title="@string/phone_accounts_all_calling_accounts"
+        android:summary="@string/phone_accounts_all_calling_accounts_summary"
+        android:persistent="false"
+        android:order="1000" >
+
+        <intent android:action="android.intent.action.MAIN"
+            android:targetPackage="com.android.server.telecom"
+            android:targetClass="com.android.server.telecom.settings.EnableAccountPreferenceActivity" />
+    </PreferenceScreen>
 
     </PreferenceCategory>
 
diff --git a/sip/src/com/android/services/telephony/sip/SipAccountRegistry.java b/sip/src/com/android/services/telephony/sip/SipAccountRegistry.java
index b54df59..b9ee69d 100644
--- a/sip/src/com/android/services/telephony/sip/SipAccountRegistry.java
+++ b/sip/src/com/android/services/telephony/sip/SipAccountRegistry.java
@@ -113,7 +113,9 @@
     }
 
     void setup(Context context) {
-        startSipProfilesAsync((Context) context, (String) null);
+        startSipProfilesAsync(context, (String) null);
+
+        // TODO: remove orphaned SIP Accounts
     }
 
     /**
@@ -121,10 +123,10 @@
      * {@link PhoneAccount}.
      *
      * @param context The context.
-     * @param sipUri The Uri of the {@link SipProfile} to start, or {@code null} for all.
+     * @param sipProfileName The name of the {@link SipProfile} to start, or {@code null} for all.
      */
-    void startSipService(Context context, String sipUri) {
-        startSipProfilesAsync((Context) context, (String) sipUri);
+    void startSipService(Context context, String sipProfileName) {
+        startSipProfilesAsync(context, sipProfileName);
     }
 
     /**
@@ -132,10 +134,10 @@
      * SIP service (this method is invoked via an intent from the SipService once a profile has
      * been stopped/closed).
      *
-     * @param sipUri The Uri of the {@link SipProfile} to remove from the registry.
+     * @param sipProfileName Name of the SIP profile.
      */
-    void removeSipProfile(String sipUri) {
-        AccountEntry accountEntry = getAccountEntry(sipUri);
+    void removeSipProfile(String sipProfileName) {
+        AccountEntry accountEntry = getAccountEntry(sipProfileName);
 
         if (accountEntry != null) {
             mAccounts.remove(accountEntry);
@@ -150,18 +152,18 @@
      * removal.
      *
      * @param context The context.
-     * @param sipUri The {@code Uri} of the sip profile.
+     * @param sipProfileName Name of the SIP profile.
      */
-    void stopSipService(Context context, String sipUri) {
+    void stopSipService(Context context, String sipProfileName) {
         // Stop the sip service for the profile.
-        AccountEntry accountEntry = getAccountEntry(sipUri);
+        AccountEntry accountEntry = getAccountEntry(sipProfileName);
         if (accountEntry != null ) {
             SipManager sipManager = SipManager.newInstance(context);
             accountEntry.stopSipService(sipManager);
         }
 
         // Un-register its PhoneAccount.
-        PhoneAccountHandle handle = SipUtil.createAccountHandle(context, sipUri);
+        PhoneAccountHandle handle = SipUtil.createAccountHandle(context, sipProfileName);
         TelecomManager.from(context).unregisterPhoneAccount(handle);
     }
 
@@ -182,28 +184,28 @@
      * specified SIP profile and registering its {@link android.telecom.PhoneAccount}.
      *
      * @param context The context.
-     * @param sipUri A specific SIP uri to start.
+     * @param sipProfileName Name of the SIP profile.
      */
-    private void startSipProfilesAsync(final Context context, final String sipUri) {
+    private void startSipProfilesAsync(final Context context, final String sipProfileName) {
         if (VERBOSE) log("startSipProfiles, start auto registration");
 
         new Thread(new Runnable() {
             @Override
             public void run() {
-                startSipProfiles(context, sipUri);
+                startSipProfiles(context, sipProfileName);
             }}
         ).start();
     }
 
     /**
      * Loops through all SIP accounts from the SIP database, starts each service and registers
-     * each with the telecom framework. If a specific sipUri is specified, this will only register
-     * the associated SIP account.
+     * each with the telecom framework. If a specific sipProfileName is specified, this will only
+     * register the associated SIP account.
      *
      * @param context The context.
-     * @param sipUri A specific SIP uri to start, or {@code null} to start all.
+     * @param sipProfileName A specific SIP profile Name to start, or {@code null} to start all.
      */
-    private void startSipProfiles(Context context, String sipUri) {
+    private void startSipProfiles(Context context, String sipProfileName) {
         final SipSharedPreferences sipSharedPreferences = new SipSharedPreferences(context);
         boolean isReceivingCalls = sipSharedPreferences.isReceivingCallsEnabled();
         String primaryProfile = sipSharedPreferences.getPrimaryAccount();
@@ -215,12 +217,9 @@
         for (SipProfile profile : sipProfileList) {
             // Register a PhoneAccount for the profile and optionally enable the primary
             // profile.
-            if (sipUri == null || Objects.equals(sipUri, profile.getUriString())) {
+            if (sipProfileName == null || sipProfileName.equals(profile.getProfileName())) {
                 PhoneAccount phoneAccount = SipUtil.createPhoneAccount(context, profile);
                 telecomManager.registerPhoneAccount(phoneAccount);
-            }
-
-            if (sipUri == null || Objects.equals(sipUri, profile.getUriString())) {
                 startSipServiceForProfile(profile, sipManager, context, isReceivingCalls);
             }
         }
@@ -253,14 +252,14 @@
     }
 
     /**
-     * Retrieves the {@link AccountEntry} from the registry with the specified Uri.
+     * Retrieves the {@link AccountEntry} from the registry with the specified name.
      *
-     * @param sipUri The Uri of the profile to retrieve.
+     * @param sipProfileName Name of the SIP profile to retrieve.
      * @return The {@link AccountEntry}, or {@code null} is it was not found.
      */
-    private AccountEntry getAccountEntry(String sipUri) {
+    private AccountEntry getAccountEntry(String sipProfileName) {
         for (AccountEntry entry : mAccounts) {
-            if (Objects.equals(sipUri, entry.getProfile().getUriString())) {
+            if (Objects.equals(sipProfileName, entry.getProfile().getProfileName())) {
                 return entry;
             }
         }
diff --git a/sip/src/com/android/services/telephony/sip/SipEditor.java b/sip/src/com/android/services/telephony/sip/SipEditor.java
index ba06711..d6f862a 100644
--- a/sip/src/com/android/services/telephony/sip/SipEditor.java
+++ b/sip/src/com/android/services/telephony/sip/SipEditor.java
@@ -249,7 +249,7 @@
     private void saveAndRegisterProfile(SipProfile p) throws IOException {
         if (p == null) return;
         mProfileDb.saveProfile(p);
-        mSipAccountRegistry.startSipService(this, p.getUriString());
+        mSipAccountRegistry.startSipService(this, p.getProfileName());
     }
 
     /**
@@ -261,7 +261,7 @@
     private void deleteAndUnregisterProfile(SipProfile p) {
         if (p == null) return;
         mProfileDb.deleteProfile(p);
-        mSipAccountRegistry.stopSipService(this, p.getUriString());
+        mSipAccountRegistry.stopSipService(this, p.getProfileName());
     }
 
     private void setRemovedProfileAndFinish() {
diff --git a/sip/src/com/android/services/telephony/sip/SipPhoneAccountSettingsActivity.java b/sip/src/com/android/services/telephony/sip/SipPhoneAccountSettingsActivity.java
index 0455346..a6f6381 100644
--- a/sip/src/com/android/services/telephony/sip/SipPhoneAccountSettingsActivity.java
+++ b/sip/src/com/android/services/telephony/sip/SipPhoneAccountSettingsActivity.java
@@ -47,8 +47,8 @@
 
             if (accountHandle != null) {
                 SipProfileDb profileDb = new SipProfileDb(this);
-                String sipUri = SipUtil.getSipUriFromPhoneAccount(accountHandle);
-                SipProfile profile = profileDb.retrieveSipProfile(sipUri);
+                String profileName = SipUtil.getSipProfileNameFromPhoneAccount(accountHandle);
+                SipProfile profile = profileDb.retrieveSipProfileFromName(profileName);
                 if (profile != null) {
                     Intent settingsIntent = new Intent(this, SipEditor.class);
                     settingsIntent.putExtra(SipSettings.KEY_SIP_PROFILE, (Parcelable) profile);
diff --git a/sip/src/com/android/services/telephony/sip/SipProfileDb.java b/sip/src/com/android/services/telephony/sip/SipProfileDb.java
index 5641af9..578c683 100644
--- a/sip/src/com/android/services/telephony/sip/SipProfileDb.java
+++ b/sip/src/com/android/services/telephony/sip/SipProfileDb.java
@@ -103,15 +103,6 @@
         }
     }
 
-    public SipProfile retrieveSipProfile(String sipUri) {
-        sipUri = sipUri.trim();
-        if (sipUri.startsWith(SCHEME_PREFIX)) {
-            return retrieveSipProfileFromName(sipUri.substring(SCHEME_PREFIX.length()));
-        }
-
-        return null;
-    }
-
     private List<SipProfile> retrieveSipProfileListInternal() {
         List<SipProfile> sipProfileList = Collections.synchronizedList(
                 new ArrayList<SipProfile>());
@@ -129,7 +120,7 @@
         return sipProfileList;
     }
 
-    private SipProfile retrieveSipProfileFromName(String name) {
+    public SipProfile retrieveSipProfileFromName(String name) {
         if (TextUtils.isEmpty(name)) {
             return null;
         }
diff --git a/sip/src/com/android/services/telephony/sip/SipSettings.java b/sip/src/com/android/services/telephony/sip/SipSettings.java
index b89a5b1..99be70f 100644
--- a/sip/src/com/android/services/telephony/sip/SipSettings.java
+++ b/sip/src/com/android/services/telephony/sip/SipSettings.java
@@ -318,7 +318,9 @@
     void deleteProfile(SipProfile p) {
         mSipProfileList.remove(p);
         SipPreference pref = mSipPreferenceMap.remove(p.getUriString());
-        mSipListContainer.removePreference(pref);
+        if (pref != null) {
+            mSipListContainer.removePreference(pref);
+        }
     }
 
     private void addProfile(SipProfile p) throws IOException {
diff --git a/sip/src/com/android/services/telephony/sip/SipUtil.java b/sip/src/com/android/services/telephony/sip/SipUtil.java
index b6d3102..e885fad 100644
--- a/sip/src/com/android/services/telephony/sip/SipUtil.java
+++ b/sip/src/com/android/services/telephony/sip/SipUtil.java
@@ -16,13 +16,10 @@
 
 package com.android.services.telephony.sip;
 
-import com.android.phone.R;
-
 import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.graphics.BitmapFactory;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.net.sip.SipManager;
@@ -34,6 +31,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.phone.R;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -73,29 +72,29 @@
     }
 
     /**
-     * Creates a {@link PhoneAccountHandle} from the specified SIP URI.
+     * Creates a {@link PhoneAccountHandle} from the specified SIP profile name.
      */
-    static PhoneAccountHandle createAccountHandle(Context context, String sipUri) {
+    static PhoneAccountHandle createAccountHandle(Context context, String sipProfileName) {
         return new PhoneAccountHandle(
-                new ComponentName(context, SipConnectionService.class), sipUri);
+                new ComponentName(context, SipConnectionService.class), sipProfileName);
     }
 
     /**
-     * Determines the SIP Uri for a specified {@link PhoneAccountHandle}.
+     * Determines the SIP profile name for a specified {@link PhoneAccountHandle}.
      *
      * @param phoneAccountHandle The {@link PhoneAccountHandle}.
-     * @return The SIP Uri.
+     * @return The SIP profile name.
      */
-    static String getSipUriFromPhoneAccount(PhoneAccountHandle phoneAccountHandle) {
+    static String getSipProfileNameFromPhoneAccount(PhoneAccountHandle phoneAccountHandle) {
         if (phoneAccountHandle == null) {
             return null;
         }
 
-        String sipUri = phoneAccountHandle.getId();
-        if (TextUtils.isEmpty(sipUri)) {
+        String sipProfileName = phoneAccountHandle.getId();
+        if (TextUtils.isEmpty(sipProfileName)) {
             return null;
         }
-        return sipUri;
+        return sipProfileName;
     }
 
     /**
@@ -110,13 +109,10 @@
         // that prototype can include transport information which we do not want to see in the
         // phone account.
         String sipAddress = profile.getUserName() + "@" + profile.getSipDomain();
-        Uri sipUri = Uri.parse(PhoneAccount.SCHEME_SIP + ":" + sipAddress);
+        Uri sipUri = Uri.parse(profile.getUriString());
 
-        // SipProfile#getUriString() is used here for legacy reasons. Changing to use the sipAddress
-        // defined above would cause SIP profiles with a TCP transport to be duplicated in the
-        // PhoneAccountRegistry since the ID would change on re-registration.
         PhoneAccountHandle accountHandle =
-                SipUtil.createAccountHandle(context, profile.getUriString());
+                SipUtil.createAccountHandle(context, profile.getProfileName());
 
         final ArrayList<String> supportedUriSchemes = new ArrayList<String>();
         supportedUriSchemes.add(PhoneAccount.SCHEME_SIP);
diff --git a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
index 34e564c..c7e6c7b 100644
--- a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
+++ b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
@@ -34,6 +34,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.Iterator;
 import java.util.List;
 
 public class PhoneAccountSettingsFragment extends PreferenceFragment
@@ -45,6 +46,7 @@
             "phone_accounts_accounts_list_category_key";
 
     private static final String DEFAULT_OUTGOING_ACCOUNT_KEY = "default_outgoing_account";
+    private static final String ALL_CALLING_ACCOUNTS_KEY = "phone_account_all_calling_accounts";
 
     private static final String CONFIGURE_CALL_ASSISTANT_PREF_KEY =
             "wifi_calling_configure_call_assistant_preference";
@@ -58,6 +60,14 @@
     private static final String USE_SIP_PREF_KEY = "use_sip_calling_options_key";
     private static final String SIP_RECEIVE_CALLS_PREF_KEY = "sip_receive_calls_key";
 
+    /**
+     * Value to start ordering of phone accounts relative to other preferences. By setting this
+     * value on the phone account listings, we ensure that anything that is ordered before
+     * {value} in the preference XML comes before the phone account list and anything with
+     * a value significantly larger will list after.
+     */
+    private static final int ACCOUNT_ORDERING_START_VALUE = 100;
+
     private String LOG_TAG = PhoneAccountSettingsFragment.class.getSimpleName();
 
     private TelecomManager mTelecomManager;
@@ -107,6 +117,10 @@
                 getPreferenceScreen().removePreference(mDefaultOutgoingAccount);
             }
 
+            Preference allAccounts = getPreferenceScreen().findPreference(ALL_CALLING_ACCOUNTS_KEY);
+            if (getNonSimCallingAccounts().size() == 0 && allAccounts != null) {
+                getPreferenceScreen().removePreference(allAccounts);
+            }
         } else {
             getPreferenceScreen().removePreference(mAccountList);
         }
@@ -362,6 +376,8 @@
             }
         });
 
+        int order = ACCOUNT_ORDERING_START_VALUE;
+
         // Add an entry for each account.
         for (PhoneAccount account : accounts) {
             PhoneAccountHandle handle = account.getAccountHandle();
@@ -407,6 +423,7 @@
                 accountPreference.setIntent(intent);
             }
 
+            accountPreference.setOrder(order++);
             mAccountList.addPreference(accountPreference);
         }
     }
@@ -426,7 +443,23 @@
 
     private boolean shouldShowConnectionServiceList() {
         return mTelephonyManager.isMultiSimEnabled() ||
-                mTelecomManager.getCallCapablePhoneAccounts().size() > 1;
+            getNonSimCallingAccounts().size() > 0;
+    }
+
+    private List<PhoneAccountHandle> getNonSimCallingAccounts() {
+        List<PhoneAccountHandle> accountHandles =
+                mTelecomManager.getCallCapablePhoneAccounts();
+        for (Iterator<PhoneAccountHandle> i = accountHandles.iterator(); i.hasNext();) {
+            PhoneAccountHandle handle = i.next();
+            PhoneAccount account = mTelecomManager.getPhoneAccount(handle);
+            if (account == null || (account.getCapabilities() &
+                    PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) != 0) {
+                // If the account is no longer valid OR the account is a built-in SIM account,
+                // remove!
+                i.remove();
+            }
+        }
+        return accountHandles;
     }
 
     private String nullToEmpty(String str) {