Add telecomm registration support to SIP.

Changes in CL:
1. Add SipAccountRegistry to manage telecom registrations
2. Register all accounts on ACTION_SIP_SERVICE_UP
3. Register specific account on ACTION_SIP_ADD_PHONE
4. Unregister specific account on ACTION_SIP_REMOVE_PHONE
5. Set the unique SIP uri as the PhoneAccount ID
6. Read phone account handle for outgoing calls instead of showing
   a proprietary SIP chooser dialog, which I removed (see
   SipProfileChooser.java).
7. Moved some of the error condition codes and error dialogs from
   SipProfileChooser to SipConnectionService.
8. Set Phone account handle as extra on the incoming-call intent
9. Remove build files for SIP directory since it is already built into
   TeleService.apk

Bug: 16836473
Bug: 16042786
Change-Id: I62d740c13ce61f181db295b9415c96ceef909177
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index b948958..66821ee 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -486,8 +486,10 @@
         </service>
         <receiver android:name="com.android.services.telephony.sip.SipBroadcastReceiver">
             <intent-filter>
-                <action android:name="com.android.phone.SIP_INCOMING_CALL" />
                 <action android:name="android.net.sip.SIP_SERVICE_UP" />
+                <action android:name="com.android.phone.SIP_INCOMING_CALL" />
+                <action android:name="com.android.phone.SIP_ADD_PHONE" />
+                <action android:name="com.android.phone.SIP_REMOVE_PHONE" />
             </intent-filter>
         </receiver>
 
diff --git a/res/drawable-hdpi/ic_dialer_sip_black_24dp.png b/res/drawable-hdpi/ic_dialer_sip_black_24dp.png
new file mode 100644
index 0000000..37dabfc
--- /dev/null
+++ b/res/drawable-hdpi/ic_dialer_sip_black_24dp.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_dialer_sip_black_24dp.png b/res/drawable-mdpi/ic_dialer_sip_black_24dp.png
new file mode 100644
index 0000000..51d5e13
--- /dev/null
+++ b/res/drawable-mdpi/ic_dialer_sip_black_24dp.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_dialer_sip_black_24dp.png b/res/drawable-xhdpi/ic_dialer_sip_black_24dp.png
new file mode 100644
index 0000000..619a79f
--- /dev/null
+++ b/res/drawable-xhdpi/ic_dialer_sip_black_24dp.png
Binary files differ
diff --git a/sip/Android.mk b/sip/Android.mk
deleted file mode 100644
index cefb86d..0000000
--- a/sip/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, res)
-
-LOCAL_JAVA_LIBRARIES := telephony-common voip-common
-
-LOCAL_PACKAGE_NAME := com.android.services.telephony.sip
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
-include $(BUILD_PACKAGE)
-include $(CLEAR_VARS)
diff --git a/sip/AndroidManifest.xml b/sip/AndroidManifest.xml
deleted file mode 100644
index 0249abd..0000000
--- a/sip/AndroidManifest.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.services.telephony.sip">
-
-</manifest>
-
diff --git a/sip/src/com/android/services/telephony/sip/SipAccountRegistry.java b/sip/src/com/android/services/telephony/sip/SipAccountRegistry.java
new file mode 100644
index 0000000..8aca613
--- /dev/null
+++ b/sip/src/com/android/services/telephony/sip/SipAccountRegistry.java
@@ -0,0 +1,166 @@
+/*
+ * 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.sip;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.net.Uri;
+import android.net.sip.SipException;
+import android.net.sip.SipManager;
+import android.net.sip.SipProfile;
+import android.telecomm.PhoneAccount;
+import android.telecomm.PhoneAccountHandle;
+import android.telecomm.TelecommManager;
+import android.util.Log;
+
+import com.android.phone.R;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Manages the {@link PhoneAccount} entries for SIP calling.
+ */
+final class SipAccountRegistry {
+    private final class AccountEntry {
+        private final SipProfile mProfile;
+
+        AccountEntry(SipProfile profile) {
+            mProfile = profile;
+        }
+
+        SipProfile getProfile() {
+            return mProfile;
+        }
+
+        boolean register(SipManager sipManager, Context context) {
+            if (VERBOSE) log("register, profile: " + mProfile);
+            try {
+                sipManager.open(
+                        mProfile,
+                        SipUtil.createIncomingCallPendingIntent(context, mProfile.getUriString()),
+                        null);
+                TelecommManager.from(context).registerPhoneAccount(createPhoneAccount(context));
+                return true;
+            } catch (SipException e) {
+                log("register, profile: " + mProfile.getProfileName() +
+                        ", exception: " + e);
+            }
+            return false;
+        }
+
+        private PhoneAccount createPhoneAccount(Context context) {
+            PhoneAccountHandle accountHandle =
+                    SipUtil.createAccountHandle(context, mProfile.getUriString());
+            return PhoneAccount.builder()
+                    .withAccountHandle(accountHandle)
+                    .withCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+                    .withHandle(Uri.parse(mProfile.getUriString()))
+                    .withLabel(mProfile.getDisplayName())
+                    .withShortDescription(mProfile.getDisplayName())
+                    .withIconResId(R.drawable.ic_dialer_sip_black_24dp)
+                    .build();
+        }
+    }
+
+    private static final String PREFIX = "[SipAccountRegistry] ";
+    private static final boolean VERBOSE = false; /* STOP SHIP if true */
+    private static final SipAccountRegistry INSTANCE = new SipAccountRegistry();
+
+    private final List<AccountEntry> mAccounts = new CopyOnWriteArrayList<>();
+
+    private SipAccountRegistry() {}
+
+    static SipAccountRegistry getInstance() {
+        return INSTANCE;
+    }
+
+    void setup(Context context) {
+        clearCurrentSipAccounts(context);
+        registerProfiles(context, null);
+    }
+
+    void addPhone(Context context, String sipUri) {
+        registerProfiles(context, sipUri);
+    }
+
+    void removePhone(Context context, String sipUri) {
+        for (AccountEntry entry : mAccounts) {
+            if (Objects.equals(sipUri, entry.getProfile().getUriString())) {
+                TelecommManager.from(context).unregisterPhoneAccount(
+                        SipUtil.createAccountHandle(context, sipUri));
+                mAccounts.remove(entry);
+                break;
+            }
+        }
+    }
+
+    /**
+     * Loops through all SIP accounts from the SIP database, starts each service and registers
+     * each with the telecomm framework. If a specific sipUri is specified, this will only register
+     * the associated SIP account.
+     *
+     * @param context The context.
+     * @param sipUri A specific SIP uri to register.
+     */
+    private void registerProfiles(final Context context, final String sipUri) {
+        if (VERBOSE) log("registerProfiles, start auto registration");
+        final SipSharedPreferences sipSharedPreferences = new SipSharedPreferences(context);
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                SipManager sipManager = SipManager.newInstance(context);
+                SipProfileDb profileDb = new SipProfileDb(context);
+                String primaryProfile = sipSharedPreferences.getPrimaryAccount();
+                List<SipProfile> sipProfileList = profileDb.retrieveSipProfileList();
+
+                for (SipProfile profile : sipProfileList) {
+                    boolean isPrimaryProfile = profile.getUriString().equals(primaryProfile);
+                    if (profile.getAutoRegistration() || isPrimaryProfile) {
+                        if (sipUri == null || Objects.equals(sipUri, profile.getUriString())) {
+                            registerAccountForProfile(profile, sipManager, context);
+                        }
+                    }
+                }
+            }}
+        ).start();
+    }
+
+    private void registerAccountForProfile(
+            SipProfile profile, SipManager sipManager, Context context) {
+        AccountEntry entry = new AccountEntry(profile);
+        if (entry.register(sipManager, context)) {
+            mAccounts.add(entry);
+        }
+    }
+
+    private void clearCurrentSipAccounts(Context context) {
+        ComponentName sipComponentName = new ComponentName(context, SipConnectionService.class);
+        TelecommManager telecommManager = TelecommManager.from(context);
+        List<PhoneAccountHandle> accountHandles = telecommManager.getEnabledPhoneAccounts();
+        for (PhoneAccountHandle handle : accountHandles) {
+            if (sipComponentName.equals(handle.getComponentName())) {
+                telecommManager.unregisterPhoneAccount(handle);
+            }
+        }
+    }
+
+    private void log(String message) {
+        Log.d(SipUtil.LOG_TAG, PREFIX + message);
+    }
+}
diff --git a/sip/src/com/android/services/telephony/sip/SipBroadcastReceiver.java b/sip/src/com/android/services/telephony/sip/SipBroadcastReceiver.java
index b891a6d..2adb61a 100644
--- a/sip/src/com/android/services/telephony/sip/SipBroadcastReceiver.java
+++ b/sip/src/com/android/services/telephony/sip/SipBroadcastReceiver.java
@@ -19,16 +19,12 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.net.sip.SipException;
 import android.net.sip.SipManager;
-import android.net.sip.SipProfile;
 import android.os.Bundle;
-import android.os.UserHandle;
+import android.telecomm.PhoneAccountHandle;
 import android.telecomm.TelecommManager;
 import android.util.Log;
 
-import java.util.List;
-
 /**
  * Broadcast receiver that handles SIP-related intents.
  */
@@ -45,10 +41,19 @@
             return;
         }
 
+        SipAccountRegistry sipAccountRegistry = SipAccountRegistry.getInstance();
         if (action.equals(SipManager.ACTION_SIP_INCOMING_CALL)) {
             takeCall(context, intent);
         } else if (action.equals(SipManager.ACTION_SIP_SERVICE_UP)) {
-            registerAllProfiles(context);
+            sipAccountRegistry.setup(context);
+        } else if (action.equals(SipManager.ACTION_SIP_ADD_PHONE)) {
+            if (VERBOSE) log("SIP_ADD_PHONE " + intent.getStringExtra(SipManager.EXTRA_LOCAL_URI));
+            sipAccountRegistry.addPhone(context, intent.getStringExtra(SipManager.EXTRA_LOCAL_URI));
+        } else if (action.equals(SipManager.ACTION_SIP_REMOVE_PHONE)) {
+            if (VERBOSE) log("SIP_REMOVE_PHONE " +
+                    intent.getStringExtra(SipManager.EXTRA_LOCAL_URI));
+            sipAccountRegistry.removePhone(
+                    context, intent.getStringExtra(SipManager.EXTRA_LOCAL_URI));
         } else {
             if (VERBOSE) log("onReceive, action not processed: " + action);
         }
@@ -56,41 +61,12 @@
 
     private void takeCall(Context context, Intent intent) {
         if (VERBOSE) log("takeCall, intent: " + intent);
-
-        Bundle extras = new Bundle();
-        extras.putParcelable(SipUtil.EXTRA_INCOMING_CALL_INTENT, intent);
-
-        TelecommManager.from(context).addNewIncomingCall(
-                SipConnectionService.getPhoneAccountHandle(context), extras);
-    }
-
-    private void registerAllProfiles(final Context context) {
-        if (VERBOSE) log("registerAllProfiles, start auto registration");
-        final SipSharedPreferences sipSharedPreferences = new SipSharedPreferences(context);
-        new Thread(new Runnable() {
-            @Override
-            public void run() {
-                SipManager sipManager = SipManager.newInstance(context);
-                SipProfileDb profileDb = new SipProfileDb(context);
-                String primaryProfile = sipSharedPreferences.getPrimaryAccount();
-
-                List<SipProfile> sipProfileList = profileDb.retrieveSipProfileList();
-
-                for (SipProfile profile : sipProfileList) {
-                    boolean isPrimaryProfile = profile.getUriString().equals(primaryProfile);
-                    if (profile.getAutoRegistration() || isPrimaryProfile) {
-                        if (VERBOSE) log("registerAllProfiles, profile: " + profile);
-                        try {
-                            sipManager.open(profile,
-                                    SipUtil.createIncomingCallPendingIntent(context), null);
-                        } catch (SipException e) {
-                            log("registerAllProfiles, profile: " + profile.getProfileName() +
-                                    ", exception: " + e);
-                        }
-                    }
-                }
-            }}
-        ).start();
+        PhoneAccountHandle accountHandle = intent.getParcelableExtra(SipUtil.EXTRA_PHONE_ACCOUNT);
+        if (accountHandle != null) {
+            Bundle extras = new Bundle();
+            extras.putParcelable(SipUtil.EXTRA_INCOMING_CALL_INTENT, intent);
+            TelecommManager.from(context).addNewIncomingCall(accountHandle, extras);
+        }
     }
 
     private static void log(String msg) {
diff --git a/sip/src/com/android/services/telephony/sip/SipConnection.java b/sip/src/com/android/services/telephony/sip/SipConnection.java
index 2603b98..2579159 100644
--- a/sip/src/com/android/services/telephony/sip/SipConnection.java
+++ b/sip/src/com/android/services/telephony/sip/SipConnection.java
@@ -31,7 +31,7 @@
 
 final class SipConnection extends Connection {
     private static final String PREFIX = "[SipConnection] ";
-    private static final boolean VERBOSE = true; /* STOP SHIP if true */
+    private static final boolean VERBOSE = false; /* STOP SHIP if true */
 
     private static final int MSG_PRECISE_CALL_STATE_CHANGED = 1;
 
diff --git a/sip/src/com/android/services/telephony/sip/SipConnectionService.java b/sip/src/com/android/services/telephony/sip/SipConnectionService.java
index 8f11935..78c0440 100644
--- a/sip/src/com/android/services/telephony/sip/SipConnectionService.java
+++ b/sip/src/com/android/services/telephony/sip/SipConnectionService.java
@@ -19,16 +19,20 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
 import android.net.sip.SipAudioCall;
 import android.net.sip.SipException;
 import android.net.sip.SipManager;
 import android.net.sip.SipProfile;
-import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.ResultReceiver;
 import android.telecomm.Connection;
 import android.telecomm.ConnectionRequest;
 import android.telecomm.ConnectionService;
 import android.telecomm.PhoneAccountHandle;
-import android.telecomm.Response;
+import android.telecomm.PropertyPresentation;
 import android.telephony.DisconnectCause;
 import android.util.Log;
 
@@ -36,9 +40,26 @@
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.sip.SipPhone;
 
+import java.util.List;
+import java.util.Objects;
+
 public final class SipConnectionService extends ConnectionService {
+    private interface IProfileFinderCallback {
+        void onFound(SipProfile profile);
+    }
+
     private static final String PREFIX = "[SipConnectionService] ";
-    private static final boolean VERBOSE = true; /* STOP SHIP if true */
+    private static final boolean VERBOSE = false; /* STOP SHIP if true */
+
+    private SipProfileDb mSipProfileDb;
+    private Handler mHandler;
+
+    @Override
+    public void onCreate() {
+        mSipProfileDb = new SipProfileDb(this);
+        mHandler = new Handler();
+        super.onCreate();
+    }
 
     static PhoneAccountHandle getPhoneAccountHandle(Context context) {
         return new PhoneAccountHandle(
@@ -52,36 +73,73 @@
             final ConnectionRequest request) {
         if (VERBOSE) log("onCreateOutgoingConnection, request: " + request);
 
+        Bundle extras = request.getExtras();
+        if (extras != null && extras.getString(SipUtil.GATEWAY_PROVIDER_PACKAGE) != null) {
+            return Connection.createFailedConnection(
+                    DisconnectCause.CALL_BARRED, "Cannot make a SIP call with a gateway number.");
+        }
+
+        PhoneAccountHandle accountHandle = request.getAccountHandle();
+        ComponentName sipComponentName = new ComponentName(this, SipConnectionService.class);
+        if (!Objects.equals(accountHandle.getComponentName(), sipComponentName)) {
+            return Connection.createFailedConnection(
+                    DisconnectCause.OUTGOING_FAILURE, "Did not match service connection");
+        }
+
+
         final SipConnection connection = new SipConnection();
+        connection.setHandle(request.getHandle(), PropertyPresentation.ALLOWED);
+        connection.setInitializing();
+        boolean attemptCall = true;
 
-        SipProfileChooser.Callback callback = new SipProfileChooser.Callback() {
-            @Override
-            public void onSipChosen(SipProfile profile) {
-                if (VERBOSE) log("onCreateOutgoingConnection, onSipChosen: " + profile);
-                com.android.internal.telephony.Connection chosenConnection =
-                        createConnectionForProfile(profile, request);
-                if (chosenConnection == null) {
-                    connection.setDisconnected(DisconnectCause.OUTGOING_CANCELED, null);
-                } else {
-                    connection.initialize(chosenConnection);
+        if (!SipUtil.isVoipSupported(this)) {
+            SipProfileChooserDialogs.showNoVoip(this, new ResultReceiver(mHandler) {
+                    @Override
+                    protected void onReceiveResult(int choice, Bundle resultData) {
+                        connection.setDisconnected(
+                                DisconnectCause.ERROR_UNSPECIFIED, "VoIP unsupported");
+                    }
+            });
+            attemptCall = false;
+        }
+
+        if (attemptCall && !isNetworkConnected()) {
+            if (VERBOSE) log("start, network not connected, dropping call");
+            SipProfileChooserDialogs.showNoInternetError(this, new ResultReceiver(mHandler) {
+                    @Override
+                    protected void onReceiveResult(int choice, Bundle resultData) {
+                        connection.setDisconnected(DisconnectCause.OUT_OF_SERVICE, null);
+                    }
+            });
+            attemptCall = false;
+        }
+
+        if (attemptCall) {
+            // The ID used for SIP-based phone account is the SIP profile Uri. Use it to find
+            // the actual profile.
+            String profileUri = accountHandle.getId();
+            findProfile(profileUri, new IProfileFinderCallback() {
+                @Override
+                public void onFound(SipProfile profile) {
+                    if (profile == null) {
+                        connection.setDisconnected(
+                                DisconnectCause.OUTGOING_FAILURE, "SIP profile not found.");
+                        connection.destroy();
+                    } else {
+                        com.android.internal.telephony.Connection chosenConnection =
+                                createConnectionForProfile(profile, request);
+                        if (chosenConnection == null) {
+                            connection.setDisconnected(
+                                    DisconnectCause.OUTGOING_FAILURE, "Connection failed.");
+                            connection.destroy();
+                        } else {
+                            if (VERBOSE) log("initializing connection");
+                            connection.initialize(chosenConnection);
+                        }
+                    }
                 }
-            }
-
-            @Override
-            public void onSipNotChosen() {
-                if (VERBOSE) log("onCreateOutgoingConnection, onSipNotChosen");
-                connection.setDisconnected(DisconnectCause.ERROR_UNSPECIFIED, null);
-            }
-
-            @Override
-            public void onCancelCall() {
-                if (VERBOSE) log("onCreateOutgoingConnection, onCancelCall");
-                connection.setDisconnected(DisconnectCause.OUTGOING_CANCELED, null);
-            }
-        };
-
-        SipProfileChooser chooser = new SipProfileChooser(this, callback);
-        chooser.start(request.getHandle(), request.getExtras());
+            });
+        }
 
         return connection;
     }
@@ -121,7 +179,9 @@
                     sipAudioCall);
             if (VERBOSE) log("onCreateIncomingConnection, new connection: " + originalConnection);
             if (originalConnection != null) {
-                return new SipConnection();
+                SipConnection sipConnection = new SipConnection();
+                sipConnection.initialize(originalConnection);
+                return sipConnection;
             } else {
                 if (VERBOSE) log("onCreateIncomingConnection, takingIncomingCall failed");
                 return Connection.createCanceledConnection();
@@ -156,6 +216,38 @@
         return null;
     }
 
+    /**
+     * Searched for the specified profile in the SIP profile database.  This can take a long time
+     * in communicating with the database, so it is done asynchronously with a separate thread and a
+     * callback interface.
+     */
+    private void findProfile(final String profileUri, final IProfileFinderCallback callback) {
+        if (VERBOSE) log("findProfile");
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                SipProfile profileToUse = null;
+                List<SipProfile> profileList = mSipProfileDb.retrieveSipProfileList();
+                if (profileList != null) {
+                    for (SipProfile profile : profileList) {
+                        if (Objects.equals(profileUri, profile.getUriString())) {
+                            profileToUse = profile;
+                            break;
+                        }
+                    }
+                }
+
+                final SipProfile profileFound = profileToUse;
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        callback.onFound(profileFound);
+                    }
+                });
+            }
+        }).start();
+    }
+
     private SipPhone findPhoneForProfile(SipProfile profile) {
         if (VERBOSE) log("findPhoneForProfile, profile: " + profile);
         for (Connection connection : getAllConnections()) {
@@ -175,7 +267,7 @@
         if (VERBOSE) log("createPhoneForProfile, profile: " + profile);
         try {
             SipManager.newInstance(this).open(profile);
-            return (SipPhone) PhoneFactory.makeSipPhone(profile.getUriString());
+            return PhoneFactory.makeSipPhone(profile.getUriString());
         } catch (SipException e) {
             log("createPhoneForProfile, exception: " + e);
             return null;
@@ -197,11 +289,17 @@
         }
     }
 
-    private ConnectionRequest getConnectionRequestForIncomingCall(ConnectionRequest request,
-            com.android.internal.telephony.Connection connection) {
-        Uri uri = Uri.fromParts(SipUtil.SCHEME_SIP, connection.getAddress(), null);
-        return new ConnectionRequest(request.getAccountHandle(), uri,
-                connection.getNumberPresentation(), request.getExtras(), 0);
+    private boolean isNetworkConnected() {
+        ConnectivityManager cm =
+                (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+        if (cm != null) {
+            NetworkInfo ni = cm.getActiveNetworkInfo();
+            if (ni != null && ni.isConnected()) {
+                return ni.getType() == ConnectivityManager.TYPE_WIFI ||
+                        !SipManager.isSipWifiOnly(this);
+            }
+        }
+        return false;
     }
 
     private static void log(String msg) {
diff --git a/sip/src/com/android/services/telephony/sip/SipEditor.java b/sip/src/com/android/services/telephony/sip/SipEditor.java
index 2f2bdef..b35f28c 100644
--- a/sip/src/com/android/services/telephony/sip/SipEditor.java
+++ b/sip/src/com/android/services/telephony/sip/SipEditor.java
@@ -52,7 +52,7 @@
 public class SipEditor extends PreferenceActivity
         implements Preference.OnPreferenceChangeListener {
     private static final String PREFIX = "[SipEditor] ";
-    private static final boolean VERBOSE = true; /* STOP SHIP if true */
+    private static final boolean VERBOSE = false; /* STOP SHIP if true */
 
     private static final int MENU_SAVE = Menu.FIRST;
     private static final int MENU_DISCARD = Menu.FIRST + 1;
@@ -249,7 +249,8 @@
         mProfileDb.saveProfile(p);
         if (p.getAutoRegistration() || mSharedPreferences.isPrimaryAccount(p.getUriString())) {
             try {
-                mSipManager.open(p, SipUtil.createIncomingCallPendingIntent(this), null);
+                mSipManager.open(
+                        p, SipUtil.createIncomingCallPendingIntent(this, p.getUriString()), null);
             } catch (Exception e) {
                 log("saveAndRegisterProfile, register failed for profile: " + p.getUriString() +
                         ", exception: " + e);
diff --git a/sip/src/com/android/services/telephony/sip/SipProfileChooser.java b/sip/src/com/android/services/telephony/sip/SipProfileChooser.java
deleted file mode 100644
index 687edfa..0000000
--- a/sip/src/com/android/services/telephony/sip/SipProfileChooser.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * 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.sip;
-
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.net.sip.SipProfile;
-import android.net.sip.SipManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ResultReceiver;
-import android.provider.Settings;
-import android.telephony.PhoneNumberUtils;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-
-import java.util.List;
-
-/** Find a SIP profile to use for the an outgoing call. */
-final class SipProfileChooser {
-    private static final String PREFIX = "[SipProfileChooser] ";
-    private static final boolean VERBOSE = true; /* STOP SHIP if true */
-
-    interface Callback {
-        // Call will be completed by the given SIP profile.
-        void onSipChosen(SipProfile profile);
-        // Call will be tried by another connection service (GSM, CDMA, etc...).
-        void onSipNotChosen();
-        // Call will be aborted.
-        void onCancelCall();
-    }
-
-    private final Context mContext;
-    private final Callback mCallback;
-    private final SipProfileDb mSipProfileDb;
-    private List<SipProfile> mProfileList;
-    private SipProfile mPrimaryProfile;
-    private final Handler mHandler = new Handler();
-
-    SipProfileChooser(Context context, Callback callback) {
-        mContext = context;
-        mCallback = callback;
-        mSipProfileDb = new SipProfileDb(mContext);
-    }
-
-    void start(Uri handle, Bundle extras) {
-        if (VERBOSE) log("start, handle: " + handle);
-
-        String scheme = handle.getScheme();
-        if (!SipUtil.SCHEME_SIP.equals(scheme) && !SipUtil.SCHEME_TEL.equals(scheme)) {
-            if (VERBOSE) log("start, unknown scheme");
-            mCallback.onSipNotChosen();
-            return;
-        }
-
-        String phoneNumber = handle.getSchemeSpecificPart();
-        // Consider "tel:[email protected]" a SIP number.
-        boolean isSipNumber = SipUtil.SCHEME_SIP.equals(scheme) ||
-                PhoneNumberUtils.isUriNumber(phoneNumber);
-        if (!SipUtil.isVoipSupported(mContext)) {
-            if (isSipNumber) {
-                if (VERBOSE) log("start, VOIP not supported, dropping call");
-                SipProfileChooserDialogs.showNoVoip(mContext, new ResultReceiver(mHandler) {
-                        @Override
-                        protected void onReceiveResult(int choice, Bundle resultData) {
-                            mCallback.onCancelCall();
-                        }
-                });
-            } else {
-                if (VERBOSE) log("start, VOIP not supported");
-                mCallback.onSipNotChosen();
-            }
-            return;
-        }
-
-        // Don't use SIP for numbers modified by a gateway.
-        if (extras != null && extras.getString(SipUtil.GATEWAY_PROVIDER_PACKAGE) != null) {
-            if (VERBOSE) log("start, not using SIP for numbers modified by gateway");
-            mCallback.onSipNotChosen();
-            return;
-        }
-
-        if (!isNetworkConnected()) {
-            if (isSipNumber) {
-                if (VERBOSE) log("start, network not connected, dropping call");
-                SipProfileChooserDialogs.showNoInternetError(mContext,
-                        new ResultReceiver(mHandler) {
-                            @Override
-                            protected void onReceiveResult(int choice, Bundle resultData) {
-                                mCallback.onCancelCall();
-                            }
-                });
-            } else {
-                if (VERBOSE) log("start, network not connected");
-                mCallback.onSipNotChosen();
-            }
-            return;
-        }
-
-        // Only ask user to pick SIP or Cell if they're actually connected to a cell network.
-        SipSharedPreferences sipPreferences = new SipSharedPreferences(mContext);
-        String callOption = sipPreferences.getSipCallOption();
-        if (callOption.equals(Settings.System.SIP_ASK_ME_EACH_TIME) && !isSipNumber &&
-                isInCellNetwork()) {
-            if (VERBOSE) log("start, call option set to ask, asking");
-            ResultReceiver receiver = new ResultReceiver(mHandler) {
-                @Override
-                protected void onReceiveResult(int choice, Bundle resultData) {
-                    if (choice == DialogInterface.BUTTON_NEGATIVE) {
-                        mCallback.onCancelCall();
-                    } else if (SipProfileChooserDialogs.isSelectedPhoneTypeSip(mContext,
-                            choice)) {
-                        buildProfileList();
-                    } else {
-                        mCallback.onSipNotChosen();
-                    }
-                }
-            };
-            SipProfileChooserDialogs.showSelectPhoneType(mContext, receiver);
-            return;
-        }
-
-        if (callOption.equals(Settings.System.SIP_ADDRESS_ONLY) && !isSipNumber) {
-            if (VERBOSE) log("start, call option set to SIP only, not a sip number");
-            mCallback.onSipNotChosen();
-            return;
-        }
-
-        if ((mSipProfileDb.getProfilesCount() == 0) && !isSipNumber) {
-            if (VERBOSE) log("start, no SIP accounts and not sip number");
-            mCallback.onSipNotChosen();
-            return;
-        }
-
-        if (VERBOSE) log("start, building profile list");
-        buildProfileList();
-    }
-
-    private boolean isNetworkConnected() {
-        ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
-                Context.CONNECTIVITY_SERVICE);
-        if (cm != null) {
-            NetworkInfo ni = cm.getActiveNetworkInfo();
-            if (ni != null && ni.isConnected()) {
-                return ni.getType() == ConnectivityManager.TYPE_WIFI ||
-                        !SipManager.isSipWifiOnly(mContext);
-            }
-        }
-        return false;
-    }
-
-    private boolean isInCellNetwork() {
-        TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
-                Context.TELEPHONY_SERVICE);
-        if (telephonyManager != null) {
-            // We'd also like to check the radio's power state but there's no public API to do this.
-            int phoneType = telephonyManager.getPhoneType();
-            return phoneType != TelephonyManager.PHONE_TYPE_NONE &&
-                    phoneType != TelephonyManager.PHONE_TYPE_SIP;
-        }
-        return false;
-    }
-
-    private void buildProfileList() {
-        if (VERBOSE) log("buildProfileList");
-        final SipSharedPreferences preferences = new SipSharedPreferences(mContext);
-        new Thread(new Runnable() {
-            @Override
-            public void run() {
-                mProfileList = mSipProfileDb.retrieveSipProfileList();
-                if (mProfileList != null) {
-                    String primarySipUri = preferences.getPrimaryAccount();
-                    for (SipProfile profile : mProfileList) {
-                        if (profile.getUriString().equals(primarySipUri)) {
-                            mPrimaryProfile = profile;
-                            break;
-                        }
-                    }
-                }
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        onBuildProfileListDone();
-                    }
-                });
-            }
-        }).start();
-    }
-
-    /**
-      * At this point we definitely want to make a SIP call, we just need to figure out which
-      * profile to use.
-      */
-    private void onBuildProfileListDone() {
-        if (VERBOSE) log("onBuildProfileListDone");
-        if (mProfileList == null || mProfileList.size() == 0) {
-            if (VERBOSE) log("onBuildProfileListDone, no profiles, showing settings dialog");
-            ResultReceiver receiver = new ResultReceiver(mHandler) {
-                @Override
-                protected void onReceiveResult(int choice, Bundle resultData) {
-                    if (choice == DialogInterface.BUTTON_POSITIVE) {
-                        openSipSettings();
-                    }
-                    mCallback.onCancelCall();
-                }
-            };
-            SipProfileChooserDialogs.showStartSipSettings(mContext, receiver);
-        } else if (mPrimaryProfile == null) {
-            if (VERBOSE) log("onBuildProfileListDone, no primary profile, showing select dialog");
-            ResultReceiver receiver = new ResultReceiver(mHandler) {
-                @Override
-                protected void onReceiveResult(int choice, Bundle resultData) {
-                    if (choice >= 0 && choice < mProfileList.size()) {
-                        SipProfile profile = mProfileList.get(choice);
-                        if (SipProfileChooserDialogs.shouldMakeSelectedProflePrimary(mContext,
-                                resultData)) {
-                            SipSharedPreferences pref = new SipSharedPreferences(mContext);
-                            pref.setPrimaryAccount(profile.getUriString());
-                        }
-                        mCallback.onSipChosen(profile);
-                    } else {
-                        mCallback.onCancelCall();
-                    }
-                }
-            };
-            SipProfileChooserDialogs.showSelectProfile(mContext, mProfileList, receiver);
-        } else {
-            mCallback.onSipChosen(mPrimaryProfile);
-        }
-    }
-
-    private void openSipSettings() {
-        Intent newIntent = new Intent(mContext, SipSettings.class);
-        newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mContext.startActivity(newIntent);
-    }
-
-    private static void log(String msg) {
-        Log.d(SipUtil.LOG_TAG, PREFIX + msg);
-    }
-}
diff --git a/sip/src/com/android/services/telephony/sip/SipProfileChooserDialogs.java b/sip/src/com/android/services/telephony/sip/SipProfileChooserDialogs.java
index 3ba633e..4eb9762 100644
--- a/sip/src/com/android/services/telephony/sip/SipProfileChooserDialogs.java
+++ b/sip/src/com/android/services/telephony/sip/SipProfileChooserDialogs.java
@@ -41,7 +41,7 @@
         implements DialogInterface.OnClickListener,
         DialogInterface.OnCancelListener, CompoundButton.OnCheckedChangeListener {
     private static final String PREFIX = "[SipProfileChooserDialogs] ";
-    private static final boolean VERBOSE = true; /* STOP SHIP if true */
+    private static final boolean VERBOSE = false; /* STOP SHIP if true */
 
     private static final String EXTRA_RESULT_RECEIVER = "result_receiver";
     private static final String EXTRA_DIALOG_ID = "dialog_id";
diff --git a/sip/src/com/android/services/telephony/sip/SipProfileDb.java b/sip/src/com/android/services/telephony/sip/SipProfileDb.java
index 7533d16..00e214f 100644
--- a/sip/src/com/android/services/telephony/sip/SipProfileDb.java
+++ b/sip/src/com/android/services/telephony/sip/SipProfileDb.java
@@ -37,7 +37,7 @@
  */
 class SipProfileDb {
     private static final String PREFIX = "[SipProfileDb] ";
-    private static final boolean VERBOSE = true; /* STOP SHIP if true */
+    private static final boolean VERBOSE = false; /* STOP SHIP if true */
 
     private static final String PROFILES_DIR = "/profiles/";
     private static final String PROFILE_OBJ_FILE = ".pobj";
diff --git a/sip/src/com/android/services/telephony/sip/SipSettings.java b/sip/src/com/android/services/telephony/sip/SipSettings.java
index f799f75..f6e6101 100644
--- a/sip/src/com/android/services/telephony/sip/SipSettings.java
+++ b/sip/src/com/android/services/telephony/sip/SipSettings.java
@@ -56,7 +56,7 @@
  */
 public class SipSettings extends PreferenceActivity {
     private static final String PREFIX = "[SipSettings] ";
-    private static final boolean VERBOSE = true; /* STOP SHIP if true */
+    private static final boolean VERBOSE = false; /* STOP SHIP if true */
 
     public static final String SIP_SHARED_PREFERENCES = "SIP_PREFERENCES";
 
@@ -227,7 +227,8 @@
             p = updateAutoRegistrationFlag(p, enabled);
             try {
                 if (enabled) {
-                    mSipManager.open(p, SipUtil.createIncomingCallPendingIntent(this), null);
+                    mSipManager.open(
+                            p, SipUtil.createIncomingCallPendingIntent(this, sipUri), null);
                 } else {
                     mSipManager.close(sipUri);
                     if (mSipSharedPreferences.isPrimaryAccount(sipUri)) {
diff --git a/sip/src/com/android/services/telephony/sip/SipSharedPreferences.java b/sip/src/com/android/services/telephony/sip/SipSharedPreferences.java
index ffb1513..ff7a3c8 100644
--- a/sip/src/com/android/services/telephony/sip/SipSharedPreferences.java
+++ b/sip/src/com/android/services/telephony/sip/SipSharedPreferences.java
@@ -29,7 +29,7 @@
  */
 public class SipSharedPreferences {
     private static final String PREFIX = "[SipSharedPreferences] ";
-    private static final boolean VERBOSE = true; /* STOP SHIP if true */
+    private static final boolean VERBOSE = false; /* STOP SHIP if true */
 
     private static final String SIP_SHARED_PREFERENCES = "SIP_PREFERENCES";
     private static final String KEY_PRIMARY_ACCOUNT = "primary";
diff --git a/sip/src/com/android/services/telephony/sip/SipUtil.java b/sip/src/com/android/services/telephony/sip/SipUtil.java
index 7a1fcf7..3d1be3d 100644
--- a/sip/src/com/android/services/telephony/sip/SipUtil.java
+++ b/sip/src/com/android/services/telephony/sip/SipUtil.java
@@ -17,15 +17,19 @@
 package com.android.services.telephony.sip;
 
 import android.app.PendingIntent;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.net.sip.SipManager;
+import android.telecomm.PhoneAccountHandle;
 import android.telecomm.TelecommManager;
 
 public class SipUtil {
     static final String LOG_TAG = "SIP";
     static final String EXTRA_INCOMING_CALL_INTENT =
             "com.android.services.telephony.sip.incoming_call_intent";
+    static final String EXTRA_PHONE_ACCOUNT =
+            "com.android.services.telephony.sip.phone_account";
     static final String GATEWAY_PROVIDER_PACKAGE =
             "com.android.phone.extra.GATEWAY_PROVIDER_PACKAGE";
     static final String SCHEME_TEL = "tel";
@@ -48,11 +52,12 @@
         return sIsVoipSupported;
     }
 
-    static PendingIntent createIncomingCallPendingIntent(Context context) {
+    static PendingIntent createIncomingCallPendingIntent(
+            Context context, String sipUri) {
         Intent intent = new Intent(context, SipBroadcastReceiver.class);
         intent.setAction(SipManager.ACTION_SIP_INCOMING_CALL);
-        return PendingIntent.getBroadcast(context, 0, intent,
-                PendingIntent.FLAG_UPDATE_CURRENT);
+        intent.putExtra(EXTRA_PHONE_ACCOUNT, SipUtil.createAccountHandle(context, sipUri));
+        return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
     }
 
     static boolean isPhoneIdle(Context context) {
@@ -63,4 +68,12 @@
         }
         return true;
     }
+
+    /**
+     * Creates a {@link PhoneAccountHandle} from the specified SIP URI.
+     */
+    static PhoneAccountHandle createAccountHandle(Context context, String sipUri) {
+        return new PhoneAccountHandle(
+                new ComponentName(context, SipConnectionService.class), sipUri);
+    }
 }
diff --git a/src/com/android/services/telephony/TelecommAccountRegistry.java b/src/com/android/services/telephony/TelecommAccountRegistry.java
index 0770f14..fedbf6b 100644
--- a/src/com/android/services/telephony/TelecommAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecommAccountRegistry.java
@@ -149,7 +149,7 @@
     }
 
     /**
-     * Sets up all the phone accounts for SIM and SIP accounts on first boot.
+     * Sets up all the phone accounts for SIMs on first boot.
      */
     void setupOnBoot() {
         IntentFilter intentFilter =
@@ -173,9 +173,20 @@
         return new PhoneAccountHandle(pstnConnectionServiceName, id);
     }
 
+    private void clearCurrentTelephonyAccounts() {
+        ComponentName telephonyComponentName =
+                new ComponentName(mContext, TelephonyConnectionService.class);
+        List<PhoneAccountHandle> accountHandles = mTelecommManager.getEnabledPhoneAccounts();
+        for (PhoneAccountHandle handle : accountHandles) {
+            if (telephonyComponentName.equals(handle.getComponentName())) {
+                mTelecommManager.unregisterPhoneAccount(handle);
+            }
+        }
+    }
+
     private void setupAccounts() {
         // Before we do anything, we need to clear whatever entries we registered at boot.
-        mTelecommManager.clearAccounts(mContext.getPackageName());
+        clearCurrentTelephonyAccounts();
 
         // Use counter to keep track of which default icon we are using
         int currAccountIcon = 0;