Merge "Import translations. DO NOT MERGE" into lmp-dev
diff --git a/src/com/android/telecomm/Call.java b/src/com/android/telecomm/Call.java
index dc3fa07..b8e2e19 100644
--- a/src/com/android/telecomm/Call.java
+++ b/src/com/android/telecomm/Call.java
@@ -17,11 +17,13 @@
 package com.android.telecomm;
 
 import android.app.PendingIntent;
+import android.content.ContentUris;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
+import android.provider.ContactsContract.Contacts;
 import android.telecomm.Connection;
 import android.telecomm.PhoneCapabilities;
 import android.telecomm.PropertyPresentation;
@@ -43,6 +45,7 @@
 import com.android.internal.telephony.CallerInfoAsyncQuery.OnQueryCompleteListener;
 import com.android.internal.telephony.SmsApplication;
 import com.android.telecomm.ContactsAsyncHelper.OnImageLoadCompleteListener;
+
 import com.google.common.base.Preconditions;
 
 import java.util.ArrayList;
@@ -81,7 +84,6 @@
         void onHandleChanged(Call call);
         void onCallerDisplayNameChanged(Call call);
         void onVideoStateChanged(Call call);
-        void onStartActivityFromInCall(Call call, PendingIntent intent);
         void onTargetPhoneAccountChanged(Call call);
         void onConnectionManagerPhoneAccountChanged(Call call);
         void onPhoneAccountChanged(Call call);
@@ -124,8 +126,6 @@
         @Override
         public void onVideoStateChanged(Call call) {}
         @Override
-        public void onStartActivityFromInCall(Call call, PendingIntent intent) {}
-        @Override
         public void onTargetPhoneAccountChanged(Call call) {}
         @Override
         public void onConnectionManagerPhoneAccountChanged(Call call) {}
@@ -331,8 +331,8 @@
             component = mConnectionService.getComponentName().flattenToShortString();
         }
 
-        return String.format(Locale.US, "[%s, %s, %s, %d]", mState, component,
-                Log.piiHandle(mHandle), getVideoState());
+        return String.format(Locale.US, "[%s, %s, %s, %s, %d]", System.identityHashCode(this),
+                mState, component, Log.piiHandle(mHandle), getVideoState());
     }
 
     int getState() {
@@ -813,6 +813,16 @@
         mExtras = extras;
     }
 
+    /**
+     * @return the uri of the contact associated with this call.
+     */
+    Uri getContactUri() {
+        if (mCallerInfo == null || !mCallerInfo.contactExists) {
+            return null;
+        }
+        return Contacts.getLookupUri(mCallerInfo.contactIdOrZero, mCallerInfo.lookupKey);
+    }
+
     Uri getRingtone() {
         return mCallerInfo == null ? null : mCallerInfo.contactRingtoneUri;
     }
@@ -1182,16 +1192,6 @@
         }
     }
 
-    public void startActivityFromInCall(PendingIntent intent) {
-        if (intent.isActivity()) {
-            for (Listener l : mListeners) {
-                l.onStartActivityFromInCall(this, intent);
-            }
-        } else {
-            Log.w(this, "startActivityFromInCall, activity intent required");
-        }
-    }
-
     static int getStateFromConnectionState(int state) {
         switch (state) {
             case Connection.STATE_INITIALIZING:
diff --git a/src/com/android/telecomm/CallActivity.java b/src/com/android/telecomm/CallActivity.java
index 0d36c8a..6d3b98f 100644
--- a/src/com/android/telecomm/CallActivity.java
+++ b/src/com/android/telecomm/CallActivity.java
@@ -149,15 +149,19 @@
         // Send to CallsManager to ensure the InCallUI gets kicked off before the broadcast returns
         Call call = mCallsManager.startOutgoingCall(handle, phoneAccountHandle, clientExtras);
 
-        NewOutgoingCallIntentBroadcaster broadcaster = new NewOutgoingCallIntentBroadcaster(
-                mCallsManager, call, intent, isDefaultDialer());
-        final int result = broadcaster.processIntent();
-        final boolean success = result == DisconnectCause.NOT_DISCONNECTED;
+        if (call == null) {
+            setResult(RESULT_CANCELED);
+        } else {
+            NewOutgoingCallIntentBroadcaster broadcaster = new NewOutgoingCallIntentBroadcaster(
+                    mCallsManager, call, intent, isDefaultDialer());
+            final int result = broadcaster.processIntent();
+            final boolean success = result == DisconnectCause.NOT_DISCONNECTED;
 
-        if (!success && call != null) {
-            disconnectCallAndShowErrorDialog(call, result);
+            if (!success && call != null) {
+                disconnectCallAndShowErrorDialog(call, result);
+            }
+            setResult(success ? RESULT_OK : RESULT_CANCELED);
         }
-        setResult(success ? RESULT_OK : RESULT_CANCELED);
     }
 
     /**
diff --git a/src/com/android/telecomm/CallsManager.java b/src/com/android/telecomm/CallsManager.java
index 8935766..784877c 100644
--- a/src/com/android/telecomm/CallsManager.java
+++ b/src/com/android/telecomm/CallsManager.java
@@ -287,7 +287,8 @@
     Call startOutgoingCall(Uri handle, PhoneAccountHandle phoneAccountHandle, Bundle extras) {
         // We only allow a single outgoing call at any given time. Before placing a call, make sure
         // there doesn't already exist another outgoing call.
-        Call call = getFirstCallWithState(CallState.NEW, CallState.DIALING);
+        Call call = getFirstCallWithState(CallState.NEW, CallState.DIALING,
+                CallState.CONNECTING, CallState.PRE_DIAL_WAIT);
 
         if (call != null) {
             Log.i(this, "Canceling simultaneous outgoing call.");
@@ -307,9 +308,11 @@
         }
 
         if (phoneAccountHandle == null) {
-            // No preset account, check if default exists
+            // No preset account, check if default exists that supports the URI scheme for the
+            // handle.
             PhoneAccountHandle defaultAccountHandle =
-                    app.getPhoneAccountRegistrar().getDefaultOutgoingPhoneAccount();
+                    app.getPhoneAccountRegistrar().getDefaultOutgoingPhoneAccount(
+                            handle.getScheme());
             if (defaultAccountHandle != null) {
                 phoneAccountHandle = defaultAccountHandle;
             }
diff --git a/src/com/android/telecomm/ConnectionServiceWrapper.java b/src/com/android/telecomm/ConnectionServiceWrapper.java
index 33f472f..787fbd0 100644
--- a/src/com/android/telecomm/ConnectionServiceWrapper.java
+++ b/src/com/android/telecomm/ConnectionServiceWrapper.java
@@ -80,7 +80,6 @@
     private static final int MSG_SET_CALLER_DISPLAY_NAME = 18;
     private static final int MSG_SET_VIDEO_STATE = 19;
     private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 20;
-    private static final int MSG_START_ACTIVITY_FROM_IN_CALL = 21;
 
     private final Handler mHandler = new Handler() {
         @Override
@@ -338,18 +337,6 @@
                     }
                     break;
                 }
-                case MSG_START_ACTIVITY_FROM_IN_CALL: {
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    try {
-                        call = mCallIdMapper.getCall(args.arg1);
-                        if (call != null) {
-                            call.startActivityFromInCall((PendingIntent) args.arg2);
-                        }
-                    } finally {
-                        args.recycle();
-                    }
-                    break;
-                }
             }
         }
     };
@@ -559,17 +546,6 @@
                 mHandler.obtainMessage(MSG_SET_CONFERENCEABLE_CONNECTIONS, args).sendToTarget();
             }
         }
-
-        @Override
-        public void startActivityFromInCall(String callId, PendingIntent intent) {
-            logIncoming("startActivityFromInCall %s %s", callId, intent);
-            if (mCallIdMapper.isValidCallId(callId)) {
-                SomeArgs args = SomeArgs.obtain();
-                args.arg1 = callId;
-                args.arg2 = intent;
-                mHandler.obtainMessage(MSG_START_ACTIVITY_FROM_IN_CALL, args).sendToTarget();
-            }
-        }
     }
 
     private final Adapter mAdapter = new Adapter();
diff --git a/src/com/android/telecomm/CreateConnectionProcessor.java b/src/com/android/telecomm/CreateConnectionProcessor.java
index cc2e8c0..fcf94cc 100644
--- a/src/com/android/telecomm/CreateConnectionProcessor.java
+++ b/src/com/android/telecomm/CreateConnectionProcessor.java
@@ -254,7 +254,7 @@
                     .getPhoneAccountRegistrar().getSimCallManager();
             CallAttemptRecord callAttemptRecord = new CallAttemptRecord(callManager,
                     TelecommApp.getInstance().getPhoneAccountRegistrar().
-                            getDefaultOutgoingPhoneAccount());
+                            getDefaultOutgoingPhoneAccount(mCall.getHandle().getScheme()));
 
             if (callManager != null && !mAttemptRecords.contains(callAttemptRecord)) {
                 Log.i(this, "Will try Connection Manager account %s for emergency",
diff --git a/src/com/android/telecomm/InCallController.java b/src/com/android/telecomm/InCallController.java
index 21581f5..f132934 100644
--- a/src/com/android/telecomm/InCallController.java
+++ b/src/com/android/telecomm/InCallController.java
@@ -61,11 +61,13 @@
     private class InCallServiceConnection implements ServiceConnection {
         /** {@inheritDoc} */
         @Override public void onServiceConnected(ComponentName name, IBinder service) {
+            Log.d(this, "onServiceConnected: %s", name);
             onConnected(name, service);
         }
 
         /** {@inheritDoc} */
         @Override public void onServiceDisconnected(ComponentName name) {
+            Log.d(this, "onDisconnected: %s", name);
             onDisconnected(name);
         }
     }
@@ -107,19 +109,6 @@
         }
 
         @Override
-        public void onStartActivityFromInCall(Call call, PendingIntent intent) {
-            if (!mInCallServices.isEmpty()) {
-                Log.i(this, "Calling startActivity, intent: %s", intent);
-                for (IInCallService inCallService : mInCallServices.values()) {
-                    try {
-                        inCallService.startActivity(mCallIdMapper.getCallId(call), intent);
-                    } catch (RemoteException ignored) {
-                    }
-                }
-            }
-        }
-
-        @Override
         public void onTargetPhoneAccountChanged(Call call) {
             updateCall(call);
         }
@@ -161,7 +150,7 @@
         if (mInCallServices.isEmpty()) {
             bind();
         } else {
-            Log.i(this, "Adding call: %s", call);
+            Log.i(this, "onCallAdded: %s", call);
             // Track the call if we don't already know about it.
             addCall(call);
 
@@ -181,6 +170,7 @@
 
     @Override
     public void onCallRemoved(Call call) {
+        Log.i(this, "onCallRemoved: %s", call);
         if (CallsManager.getInstance().getCalls().isEmpty()) {
             // TODO: Wait for all messages to be delivered to the service before unbinding.
             unbind();
@@ -322,6 +312,8 @@
     private void onConnected(ComponentName componentName, IBinder service) {
         ThreadUtil.checkOnMainThread();
 
+        Log.i(this, "onConnected to %s", componentName);
+
         IInCallService inCallService = IInCallService.Stub.asInterface(service);
 
         try {
@@ -336,9 +328,12 @@
         // Upon successful connection, send the state of the world to the service.
         ImmutableCollection<Call> calls = CallsManager.getInstance().getCalls();
         if (!calls.isEmpty()) {
+            Log.i(this, "Adding %s calls to InCallService after onConnected: %s", calls.size(),
+                    componentName);
             for (Call call : calls) {
                 try {
                     // Track the call if we don't already know about it.
+                    Log.i(this, "addCall after binding: %s", call);
                     addCall(call);
 
                     inCallService.addCall(toParcelableCall(call,
@@ -358,6 +353,7 @@
      * @param disconnectedComponent The {@link ComponentName} of the service which disconnected.
      */
     private void onDisconnected(ComponentName disconnectedComponent) {
+        Log.i(this, "onDisconnected from %s", disconnectedComponent);
         ThreadUtil.checkOnMainThread();
         if (mInCallServices.containsKey(disconnectedComponent)) {
             mInCallServices.remove(disconnectedComponent);
diff --git a/src/com/android/telecomm/PhoneAccountRegistrar.java b/src/com/android/telecomm/PhoneAccountRegistrar.java
index f7cce27..f7652d7 100644
--- a/src/com/android/telecomm/PhoneAccountRegistrar.java
+++ b/src/com/android/telecomm/PhoneAccountRegistrar.java
@@ -21,6 +21,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.provider.Settings;
 import android.telecomm.ConnectionService;
 import android.telecomm.PhoneAccount;
 import android.telecomm.PhoneAccountHandle;
@@ -47,6 +48,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.Integer;
 import java.lang.SecurityException;
 import java.lang.String;
 import java.util.ArrayList;
@@ -75,6 +77,11 @@
     }
 
     private static final String FILE_NAME = "phone-account-registrar-state.xml";
+    @VisibleForTesting
+    public static final int EXPECTED_STATE_VERSION = 2;
+
+    /** Keep in sync with the same in SipSettings.java */
+    private static final String SIP_SHARED_PREFERENCES = "SIP_PREFERENCES";
 
     private final List<Listener> mListeners = new CopyOnWriteArrayList<>();
     private final AtomicFile mAtomicFile;
@@ -94,13 +101,24 @@
         read();
     }
 
-    public PhoneAccountHandle getDefaultOutgoingPhoneAccount() {
+    /**
+     * Retrieves the default outgoing phone account supporting the specified uriScheme.
+     * @param uriScheme The URI scheme for the outgoing call.
+     * @return The {@link PhoneAccountHandle} to use.
+     */
+    public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme) {
         final PhoneAccountHandle userSelected = getUserSelectedOutgoingPhoneAccount();
+
         if (userSelected != null) {
-            return userSelected;
+            // If there is a default PhoneAccount, ensure it supports calls to handles with the
+            // specified uriScheme.
+            final PhoneAccount userSelectedAccount = getPhoneAccount(userSelected);
+            if (userSelectedAccount.supportsUriScheme(uriScheme)) {
+                return userSelected;
+            }
         }
 
-        List<PhoneAccountHandle> outgoing = getOutgoingPhoneAccounts();
+        List<PhoneAccountHandle> outgoing = getOutgoingPhoneAccounts(uriScheme);
         switch (outgoing.size()) {
             case 0:
                 // There are no accounts, so there can be no default
@@ -249,6 +267,10 @@
         return getPhoneAccountHandles(PhoneAccount.CAPABILITY_CALL_PROVIDER);
     }
 
+    public List<PhoneAccountHandle> getOutgoingPhoneAccounts(String uriScheme) {
+        return getPhoneAccountHandles(PhoneAccount.CAPABILITY_CALL_PROVIDER, uriScheme);
+    }
+
     public List<PhoneAccountHandle> getAllConnectionManagerPhoneAccounts() {
         if (isEnabledConnectionManager()) {
             return getPhoneAccountHandles(PhoneAccount.CAPABILITY_CONNECTION_MANAGER);
@@ -392,11 +414,25 @@
 
     /**
      * Returns a list of phone account handles with the specified flag.
+     *
+     * @param flags Flags which the {@code PhoneAccount} must have.
      */
     private List<PhoneAccountHandle> getPhoneAccountHandles(int flags) {
+        return getPhoneAccountHandles(flags, null);
+    }
+
+    /**
+     * Returns a list of phone account handles with the specified flag, supporting the specified
+     * URI scheme.
+     *
+     * @param flags Flags which the {@code PhoneAccount} must have.
+     * @param uriScheme URI schemes the PhoneAccount must handle.  {@code Null} bypasses the
+     *                  URI scheme check.
+     */
+    private List<PhoneAccountHandle> getPhoneAccountHandles(int flags, String uriScheme) {
         List<PhoneAccountHandle> accountHandles = new ArrayList<>();
         for (PhoneAccount m : mState.accounts) {
-            if (has(m, flags)) {
+            if (has(m, flags) && (uriScheme == null || m.supportsUriScheme(uriScheme))) {
                 accountHandles.add(m.getAccountHandle());
             }
         }
@@ -424,6 +460,11 @@
          * The complete list of {@code PhoneAccount}s known to the Telecomm subsystem.
          */
         public final List<PhoneAccount> accounts = new ArrayList<>();
+
+        /**
+         * The version number of the State data.
+         */
+        public int versionNumber;
     }
 
     ////////////////////////////////////////////////////////////////////////////////////////////////
@@ -462,12 +503,16 @@
             return;
         }
 
+        boolean versionChanged = false;
+
         XmlPullParser parser;
         try {
             parser = Xml.newPullParser();
             parser.setInput(new BufferedInputStream(is), null);
             parser.nextTag();
-            mState = readFromXml(parser);
+            mState = readFromXml(parser, mContext);
+            versionChanged = mState.versionNumber < EXPECTED_STATE_VERSION;
+
         } catch (IOException | XmlPullParserException e) {
             Log.e(this, e, "Reading state from XML file");
             mState = new State();
@@ -478,6 +523,11 @@
                 Log.e(this, e, "Closing InputStream");
             }
         }
+
+        // If an upgrade occurred, write out the changed data.
+        if (versionChanged) {
+            write();
+        }
     }
 
     private static void writeToXml(State state, XmlSerializer serializer)
@@ -485,9 +535,9 @@
         sStateXml.writeToXml(state, serializer);
     }
 
-    private static State readFromXml(XmlPullParser parser)
+    private static State readFromXml(XmlPullParser parser, Context context)
             throws IOException, XmlPullParserException {
-        State s = sStateXml.readFromXml(parser);
+        State s = sStateXml.readFromXml(parser, 0, context);
         return s != null ? s : new State();
     }
 
@@ -498,6 +548,9 @@
 
     @VisibleForTesting
     public abstract static class XmlSerialization<T> {
+        private static final String LENGTH_ATTRIBUTE = "length";
+        private static final String VALUE_TAG = "value";
+
         /**
          * Write the supplied object to XML
          */
@@ -511,7 +564,7 @@
          * object's writeToXml(). This object tries to fail early without modifying
          * 'parser' if it does not recognize the data it sees.
          */
-        public abstract T readFromXml(XmlPullParser parser)
+        public abstract T readFromXml(XmlPullParser parser, int version, Context context)
                 throws IOException, XmlPullParserException;
 
         protected void writeTextSafely(String tagName, Object value, XmlSerializer serializer)
@@ -522,6 +575,66 @@
                 serializer.endTag(null, tagName);
             }
         }
+
+        /**
+         * Serializes a string array.
+         *
+         * @param tagName The tag name for the string array.
+         * @param values The string values to serialize.
+         * @param serializer The serializer.
+         * @throws IOException
+         */
+        protected void writeStringList(String tagName, List<String> values,
+                XmlSerializer serializer)
+                throws IOException {
+
+            serializer.startTag(null, tagName);
+            if (values != null) {
+                serializer.attribute(null, LENGTH_ATTRIBUTE, Objects.toString(values.size()));
+                for (String toSerialize : values) {
+                    serializer.startTag(null, VALUE_TAG);
+                    if (toSerialize != null ){
+                        serializer.text(toSerialize);
+                    }
+
+                    serializer.endTag(null, VALUE_TAG);
+                }
+            } else {
+                serializer.attribute(null, LENGTH_ATTRIBUTE, "0");
+            }
+            serializer.endTag(null, tagName);
+
+        }
+
+        /**
+         * Reads a string array from the XML parser.
+         *
+         * @param parser The XML parser.
+         * @return String array containing the parsed values.
+         * @throws IOException Exception related to IO.
+         * @throws XmlPullParserException Exception related to parsing.
+         */
+        protected List<String> readStringList(XmlPullParser parser)
+                throws IOException, XmlPullParserException {
+
+            int length = Integer.parseInt(parser.getAttributeValue(null, LENGTH_ATTRIBUTE));
+            List<String> arrayEntries = new ArrayList<String>(length);
+            String value = null;
+
+            if (length == 0) {
+                return arrayEntries;
+            }
+
+            int outerDepth = parser.getDepth();
+            while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+                if (parser.getName().equals(VALUE_TAG)) {
+                    value = parser.getText();
+                    arrayEntries.add(value);
+                }
+            }
+
+            return arrayEntries;
+        }
     }
 
     @VisibleForTesting
@@ -531,12 +644,14 @@
         private static final String DEFAULT_OUTGOING = "default_outgoing";
         private static final String SIM_CALL_MANAGER = "sim_call_manager";
         private static final String ACCOUNTS = "accounts";
+        private static final String VERSION = "version";
 
         @Override
         public void writeToXml(State o, XmlSerializer serializer)
                 throws IOException {
             if (o != null) {
                 serializer.startTag(null, CLASS_STATE);
+                serializer.attribute(null, VERSION, Objects.toString(EXPECTED_STATE_VERSION));
 
                 if (o.defaultOutgoing != null) {
                     serializer.startTag(null, DEFAULT_OUTGOING);
@@ -561,23 +676,32 @@
         }
 
         @Override
-        public State readFromXml(XmlPullParser parser)
+        public State readFromXml(XmlPullParser parser, int version, Context context)
                 throws IOException, XmlPullParserException {
             if (parser.getName().equals(CLASS_STATE)) {
                 State s = new State();
+
+                String rawVersion = parser.getAttributeValue(null, VERSION);
+                s.versionNumber = TextUtils.isEmpty(rawVersion) ? 1 :
+                        Integer.parseInt(rawVersion);
+
                 int outerDepth = parser.getDepth();
                 while (XmlUtils.nextElementWithin(parser, outerDepth)) {
                     if (parser.getName().equals(DEFAULT_OUTGOING)) {
                         parser.nextTag();
-                        s.defaultOutgoing = sPhoneAccountHandleXml.readFromXml(parser);
+                        s.defaultOutgoing = sPhoneAccountHandleXml.readFromXml(parser,
+                                s.versionNumber, context);
                     } else if (parser.getName().equals(SIM_CALL_MANAGER)) {
                         parser.nextTag();
-                        s.simCallManager = sPhoneAccountHandleXml.readFromXml(parser);
+                        s.simCallManager = sPhoneAccountHandleXml.readFromXml(parser,
+                                s.versionNumber, context);
                     } else if (parser.getName().equals(ACCOUNTS)) {
                         int accountsDepth = parser.getDepth();
                         while (XmlUtils.nextElementWithin(parser, accountsDepth)) {
-                            PhoneAccount account = sPhoneAccountXml.readFromXml(parser);
-                            if (account != null) {
+                            PhoneAccount account = sPhoneAccountXml.readFromXml(parser,
+                                    s.versionNumber, context);
+
+                            if (account != null && s.accounts != null) {
                                 s.accounts.add(account);
                             }
                         }
@@ -600,6 +724,7 @@
         private static final String ICON_RES_ID = "icon_res_id";
         private static final String LABEL = "label";
         private static final String SHORT_DESCRIPTION = "short_description";
+        private static final String SUPPORTED_URI_SCHEMES = "supported_uri_schemes";
 
         @Override
         public void writeToXml(PhoneAccount o, XmlSerializer serializer)
@@ -619,13 +744,13 @@
                 writeTextSafely(ICON_RES_ID, Integer.toString(o.getIconResId()), serializer);
                 writeTextSafely(LABEL, o.getLabel(), serializer);
                 writeTextSafely(SHORT_DESCRIPTION, o.getShortDescription(), serializer);
+                writeStringList(SUPPORTED_URI_SCHEMES, o.getSupportedUriSchemes(), serializer);
 
                 serializer.endTag(null, CLASS_PHONE_ACCOUNT);
             }
         }
 
-        @Override
-        public PhoneAccount readFromXml(XmlPullParser parser)
+        public PhoneAccount readFromXml(XmlPullParser parser, int version, Context context)
                 throws IOException, XmlPullParserException {
             if (parser.getName().equals(CLASS_PHONE_ACCOUNT)) {
                 int outerDepth = parser.getDepth();
@@ -636,11 +761,13 @@
                 int iconResId = 0;
                 String label = null;
                 String shortDescription = null;
+                List<String> supportedUriSchemes = null;
 
                 while (XmlUtils.nextElementWithin(parser, outerDepth)) {
                     if (parser.getName().equals(ACCOUNT_HANDLE)) {
                         parser.nextTag();
-                        accountHandle = sPhoneAccountHandleXml.readFromXml(parser);
+                        accountHandle = sPhoneAccountHandleXml.readFromXml(parser, version,
+                                context);
                     } else if (parser.getName().equals(HANDLE)) {
                         parser.next();
                         handle = Uri.parse(parser.getText());
@@ -659,8 +786,32 @@
                     } else if (parser.getName().equals(SHORT_DESCRIPTION)) {
                         parser.next();
                         shortDescription = parser.getText();
+                    } else if (parser.getName().equals(SUPPORTED_URI_SCHEMES)) {
+                        supportedUriSchemes = readStringList(parser);
                     }
                 }
+
+                // Upgrade older phone accounts to specify the supported URI schemes.
+                if (version < 2) {
+                    ComponentName sipComponentName = new ComponentName("com.android.phone",
+                            "com.android.services.telephony.sip.SipConnectionService");
+
+                    supportedUriSchemes = new ArrayList<>();
+
+                    // Handle the SIP connection service.
+                    // Check the system settings to see if it also should handle "tel" calls.
+                    if (accountHandle.getComponentName().equals(sipComponentName)) {
+                        boolean useSipForPstn = useSipForPstnCalls(context);
+                        supportedUriSchemes.add(PhoneAccount.SCHEME_SIP);
+                        if (useSipForPstn) {
+                            supportedUriSchemes.add(PhoneAccount.SCHEME_TEL);
+                        }
+                    } else {
+                        supportedUriSchemes.add(PhoneAccount.SCHEME_TEL);
+                        supportedUriSchemes.add(PhoneAccount.SCHEME_VOICEMAIL);
+                    }
+                }
+
                 return PhoneAccount.builder()
                         .withAccountHandle(accountHandle)
                         .withHandle(handle)
@@ -669,10 +820,24 @@
                         .withIconResId(iconResId)
                         .withLabel(label)
                         .withShortDescription(shortDescription)
+                        .withSupportedUriSchemes(supportedUriSchemes)
                         .build();
             }
             return null;
         }
+
+        /**
+         * Determines if the SIP call settings specify to use SIP for all calls, including PSTN calls.
+         *
+         * @param context The context.
+         * @return {@code True} if SIP should be used for all calls.
+         */
+        private boolean useSipForPstnCalls(Context context) {
+            String option = Settings.System.getString(context.getContentResolver(),
+                    Settings.System.SIP_CALL_OPTIONS);
+            option = (option != null) ? option : Settings.System.SIP_ADDRESS_ONLY;
+            return option.equals(Settings.System.SIP_ALWAYS);
+        }
     };
 
     @VisibleForTesting
@@ -700,7 +865,7 @@
         }
 
         @Override
-        public PhoneAccountHandle readFromXml(XmlPullParser parser)
+        public PhoneAccountHandle readFromXml(XmlPullParser parser, int version, Context context)
                 throws IOException, XmlPullParserException {
             if (parser.getName().equals(CLASS_PHONE_ACCOUNT_HANDLE)) {
                 String componentNameString = null;
diff --git a/src/com/android/telecomm/ProximitySensorManager.java b/src/com/android/telecomm/ProximitySensorManager.java
index 287c6d4..7b8773d 100644
--- a/src/com/android/telecomm/ProximitySensorManager.java
+++ b/src/com/android/telecomm/ProximitySensorManager.java
@@ -52,6 +52,11 @@
      * Turn the proximity sensor on.
      */
     void turnOn() {
+        if (CallsManager.getInstance().getCalls().isEmpty()) {
+            Log.w(this, "Asking to turn on prox sensor without a call? I don't think so.");
+            return;
+        }
+
         if (mProximityWakeLock == null) {
             return;
         }
diff --git a/src/com/android/telecomm/QuickResponseUtils.java b/src/com/android/telecomm/QuickResponseUtils.java
new file mode 100644
index 0000000..ead9105
--- /dev/null
+++ b/src/com/android/telecomm/QuickResponseUtils.java
@@ -0,0 +1,116 @@
+/*
+ * 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.telecomm;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+
+
+/**
+ * Utils class that exposes some helper routines to used to manage the QuickResponses
+ */
+public class QuickResponseUtils {
+    public static final String LOG_TAG = "QuickResponseUtils";
+
+    // SharedPreferences file name for our persistent settings.
+    public static final String SHARED_PREFERENCES_NAME = "respond_via_sms_prefs";
+    private static final String PACKAGE_NAME_TELEPHONY = "com.android.phone";
+
+    // Preference keys for the 4 "canned responses"; see RespondViaSmsManager$Settings.
+    // Since (for now at least) the number of messages is fixed at 4, and since
+    // SharedPreferences can't deal with arrays anyway, just store the messages
+    // as 4 separate strings.
+    public static final int NUM_CANNED_RESPONSES = 4;
+    public static final String KEY_CANNED_RESPONSE_PREF_1 = "canned_response_pref_1";
+    public static final String KEY_CANNED_RESPONSE_PREF_2 = "canned_response_pref_2";
+    public static final String KEY_CANNED_RESPONSE_PREF_3 = "canned_response_pref_3";
+    public static final String KEY_CANNED_RESPONSE_PREF_4 = "canned_response_pref_4";
+
+    /**
+     * As of L, QuickResponses were moved from Telephony to Telecomm. Because of
+     * this, we need to make sure that we migrate any old QuickResponses to our
+     * current SharedPreferences.  This is a lazy migration as it happens only when
+     * the QuickResponse settings are viewed or if they are queried via RespondViaSmsManager.
+     */
+    public static void maybeMigrateLegacyQuickResponses() {
+        // The algorithm will go as such:
+        // If Telecomm QuickResponses exist, we will skip migration because this implies
+        // that a user has already specified their desired QuickResponses and have abandoned any
+        // older QuickResponses.
+        // Then, if Telephony QuickResponses exist, we will move those to Telecomm.
+        // If neither exist, we'll populate Telecomm with the default QuickResponses.
+        // This guarantees the caller that QuickResponses exist in SharedPreferences after this
+        // function is called.
+
+        Log.d(LOG_TAG, "maybeMigrateLegacyQuickResponses() - Starting");
+
+        final Context telecommContext = TelecommApp.getInstance();
+        final SharedPreferences prefs = telecommContext.getSharedPreferences(
+                SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
+        final Resources res = telecommContext.getResources();
+
+        final boolean responsesExist = prefs.contains(KEY_CANNED_RESPONSE_PREF_1);
+        if (responsesExist) {
+            // If one QuickResponse exists, they all exist.
+            Log.d(LOG_TAG, "maybeMigrateLegacyQuickResponses() - Telecomm QuickResponses exist");
+            return;
+        }
+
+        // Grab the all the default QuickResponses from our resources.
+        String cannedResponse1 = res.getString(R.string.respond_via_sms_canned_response_1);
+        String cannedResponse2 = res.getString(R.string.respond_via_sms_canned_response_2);
+        String cannedResponse3 = res.getString(R.string.respond_via_sms_canned_response_3);
+        String cannedResponse4 = res.getString(R.string.respond_via_sms_canned_response_4);
+
+        Log.d(LOG_TAG, "maybeMigrateLegacyQuickResponses() - No local QuickResponses");
+
+        // We don't have local QuickResponses, let's see if they live in
+        // the Telephony package and we'll fall back on using our default values.
+        Context telephonyContext = null;
+        try {
+            telephonyContext = telecommContext.createPackageContext(PACKAGE_NAME_TELEPHONY, 0);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(LOG_TAG, e, "maybeMigrateLegacyQuickResponses() - Can't find Telephony package.");
+        }
+
+        // Read the old canned responses from the Telephony SharedPreference if possible.
+        if (telephonyContext != null) {
+            // Note that if any one QuickResponse does not exist, we'll use the default
+            // value to populate it.
+            Log.d(LOG_TAG, "maybeMigrateLegacyQuickResponses() - Using Telephony QuickResponses.");
+            final SharedPreferences oldPrefs = telephonyContext.getSharedPreferences(
+                    SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
+            cannedResponse1 = oldPrefs.getString(KEY_CANNED_RESPONSE_PREF_1, cannedResponse1);
+            cannedResponse2 = oldPrefs.getString(KEY_CANNED_RESPONSE_PREF_2, cannedResponse2);
+            cannedResponse3 = oldPrefs.getString(KEY_CANNED_RESPONSE_PREF_3, cannedResponse3);
+            cannedResponse4 = oldPrefs.getString(KEY_CANNED_RESPONSE_PREF_4, cannedResponse4);
+        }
+
+        // Either way, write them back into Telecomm SharedPreferences.
+        final SharedPreferences.Editor editor = prefs.edit();
+        editor.putString(KEY_CANNED_RESPONSE_PREF_1, cannedResponse1);
+        editor.putString(KEY_CANNED_RESPONSE_PREF_2, cannedResponse2);
+        editor.putString(KEY_CANNED_RESPONSE_PREF_3, cannedResponse3);
+        editor.putString(KEY_CANNED_RESPONSE_PREF_4, cannedResponse4);
+        editor.commit();
+
+        Log.d(LOG_TAG, "maybeMigrateLegacyQuickResponses() - Done.");
+        return;
+    }
+}
diff --git a/src/com/android/telecomm/RespondViaSmsManager.java b/src/com/android/telecomm/RespondViaSmsManager.java
index 8618af0..f1e6033 100644
--- a/src/com/android/telecomm/RespondViaSmsManager.java
+++ b/src/com/android/telecomm/RespondViaSmsManager.java
@@ -40,19 +40,6 @@
 public class RespondViaSmsManager extends CallsManagerListenerBase {
     private static final String SCHEME_SMSTO = "smsto";
 
-    /** SharedPreferences file name for our persistent settings. */
-    private static final String SHARED_PREFERENCES_NAME = "respond_via_sms_prefs";
-
-    // Preference keys for the 4 "canned responses"; see RespondViaSmsManager$Settings.
-    // Since (for now at least) the number of messages is fixed at 4, and since
-    // SharedPreferences can't deal with arrays anyway, just store the messages
-    // as 4 separate strings.
-    private static final int NUM_CANNED_RESPONSES = 4;
-    private static final String KEY_CANNED_RESPONSE_PREF_1 = "canned_response_pref_1";
-    private static final String KEY_CANNED_RESPONSE_PREF_2 = "canned_response_pref_2";
-    private static final String KEY_CANNED_RESPONSE_PREF_3 = "canned_response_pref_3";
-    private static final String KEY_CANNED_RESPONSE_PREF_4 = "canned_response_pref_4";
-
     private static final int MSG_CANNED_TEXT_MESSAGES_READY = 1;
     private static final int MSG_SHOW_SENT_TOAST = 2;
 
@@ -104,22 +91,28 @@
             @Override
             public void run() {
                 Log.d(RespondViaSmsManager.this, "loadCannedResponses() starting");
+
+                // This function guarantees that QuickResponses will be in our
+                // SharedPreferences with the proper values considering there may be
+                // old QuickResponses in Telephony pre L.
+                QuickResponseUtils.maybeMigrateLegacyQuickResponses();
+
                 final SharedPreferences prefs = TelecommApp.getInstance().getSharedPreferences(
-                        SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
+                        QuickResponseUtils.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
                 final Resources res = TelecommApp.getInstance().getInstance().getResources();
 
-                final ArrayList<String> textMessages = new ArrayList<>(NUM_CANNED_RESPONSES);
+                final ArrayList<String> textMessages = new ArrayList<>(
+                        QuickResponseUtils.NUM_CANNED_RESPONSES);
 
                 // Note the default values here must agree with the corresponding
                 // android:defaultValue attributes in respond_via_sms_settings.xml.
-
-                textMessages.add(0, prefs.getString(KEY_CANNED_RESPONSE_PREF_1,
+                textMessages.add(0, prefs.getString(QuickResponseUtils.KEY_CANNED_RESPONSE_PREF_1,
                         res.getString(R.string.respond_via_sms_canned_response_1)));
-                textMessages.add(1, prefs.getString(KEY_CANNED_RESPONSE_PREF_2,
+                textMessages.add(1, prefs.getString(QuickResponseUtils.KEY_CANNED_RESPONSE_PREF_2,
                         res.getString(R.string.respond_via_sms_canned_response_2)));
-                textMessages.add(2, prefs.getString(KEY_CANNED_RESPONSE_PREF_3,
+                textMessages.add(2, prefs.getString(QuickResponseUtils.KEY_CANNED_RESPONSE_PREF_3,
                         res.getString(R.string.respond_via_sms_canned_response_3)));
-                textMessages.add(3, prefs.getString(KEY_CANNED_RESPONSE_PREF_4,
+                textMessages.add(3, prefs.getString(QuickResponseUtils.KEY_CANNED_RESPONSE_PREF_4,
                         res.getString(R.string.respond_via_sms_canned_response_4)));
 
                 Log.d(RespondViaSmsManager.this,
diff --git a/src/com/android/telecomm/RespondViaSmsSettings.java b/src/com/android/telecomm/RespondViaSmsSettings.java
index 231dbaa..ecca39c 100644
--- a/src/com/android/telecomm/RespondViaSmsSettings.java
+++ b/src/com/android/telecomm/RespondViaSmsSettings.java
@@ -19,9 +19,7 @@
 import android.app.ActionBar;
 import android.app.Activity;
 import android.content.Context;
-import android.content.Intent;
 import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.preference.EditTextPreference;
 import android.preference.Preference;
@@ -33,18 +31,6 @@
  * Helper class to manage the "Respond via SMS Message" feature for incoming calls.
  */
 public class RespondViaSmsSettings {
-    /** SharedPreferences file name for our persistent settings. */
-    private static final String SHARED_PREFERENCES_NAME = "respond_via_sms_prefs";
-
-    // Preference keys for the 4 "canned responses"; see RespondViaSmsManager$Settings.
-    // Since (for now at least) the number of messages is fixed at 4, and since
-    // SharedPreferences can't deal with arrays anyway, just store the messages
-    // as 4 separate strings.
-    private static final int NUM_CANNED_RESPONSES = 4;
-    private static final String KEY_CANNED_RESPONSE_PREF_1 = "canned_response_pref_1";
-    private static final String KEY_CANNED_RESPONSE_PREF_2 = "canned_response_pref_2";
-    private static final String KEY_CANNED_RESPONSE_PREF_3 = "canned_response_pref_3";
-    private static final String KEY_CANNED_RESPONSE_PREF_4 = "canned_response_pref_4";
     private static final String KEY_PREFERRED_PACKAGE = "preferred_package_pref";
     private static final String KEY_INSTANT_TEXT_DEFAULT_COMPONENT = "instant_text_def_component";
 
@@ -63,7 +49,13 @@
             super.onCreate(icicle);
             Log.d(this, "Settings: onCreate()...");
 
-            getPreferenceManager().setSharedPreferencesName(SHARED_PREFERENCES_NAME);
+            // This function guarantees that QuickResponses will be in our
+            // SharedPreferences with the proper values considering there may be
+            // old QuickResponses in Telephony pre L.
+            QuickResponseUtils.maybeMigrateLegacyQuickResponses();
+
+            getPreferenceManager().setSharedPreferencesName(
+                    QuickResponseUtils.SHARED_PREFERENCES_NAME);
 
             // This preference screen is ultra-simple; it's just 4 plain
             // <EditTextPreference>s, one for each of the 4 "canned responses".
@@ -79,19 +71,23 @@
             addPreferencesFromResource(R.xml.respond_via_sms_settings);
 
             EditTextPreference pref;
-            pref = (EditTextPreference) findPreference(KEY_CANNED_RESPONSE_PREF_1);
+            pref = (EditTextPreference) findPreference(
+                    QuickResponseUtils.KEY_CANNED_RESPONSE_PREF_1);
             pref.setTitle(pref.getText());
             pref.setOnPreferenceChangeListener(this);
 
-            pref = (EditTextPreference) findPreference(KEY_CANNED_RESPONSE_PREF_2);
+            pref = (EditTextPreference) findPreference(
+                    QuickResponseUtils.KEY_CANNED_RESPONSE_PREF_2);
             pref.setTitle(pref.getText());
             pref.setOnPreferenceChangeListener(this);
 
-            pref = (EditTextPreference) findPreference(KEY_CANNED_RESPONSE_PREF_3);
+            pref = (EditTextPreference) findPreference(
+                    QuickResponseUtils.KEY_CANNED_RESPONSE_PREF_3);
             pref.setTitle(pref.getText());
             pref.setOnPreferenceChangeListener(this);
 
-            pref = (EditTextPreference) findPreference(KEY_CANNED_RESPONSE_PREF_4);
+            pref = (EditTextPreference) findPreference(
+                    QuickResponseUtils.KEY_CANNED_RESPONSE_PREF_4);
             pref.setTitle(pref.getText());
             pref.setOnPreferenceChangeListener(this);
 
@@ -130,7 +126,7 @@
                 case R.id.respond_via_message_reset:
                     // Reset the preferences settings
                     SharedPreferences prefs = getSharedPreferences(
-                            SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
+                            QuickResponseUtils.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
                     SharedPreferences.Editor editor = prefs.edit();
                     editor.remove(KEY_INSTANT_TEXT_DEFAULT_COMPONENT);
                     editor.apply();
diff --git a/src/com/android/telecomm/Ringer.java b/src/com/android/telecomm/Ringer.java
index 7741eab..9c554ce 100644
--- a/src/com/android/telecomm/Ringer.java
+++ b/src/com/android/telecomm/Ringer.java
@@ -16,9 +16,13 @@
 
 package com.android.telecomm;
 
+import android.app.Notification;
+import android.app.NotificationManager;
 import android.content.Context;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
+import android.net.Uri;
+import android.os.Bundle;
 import android.os.SystemVibrator;
 import android.os.Vibrator;
 import android.provider.Settings;
@@ -174,6 +178,10 @@
             // The foreground call is one of incoming calls so play the ringer out loud.
             stopCallWaiting();
 
+            if (!shouldRingForContact(foregroundCall.getContactUri())) {
+                return;
+            }
+
             AudioManager audioManager =
                     (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
             if (audioManager.getStreamVolume(AudioManager.STREAM_RING) > 0) {
@@ -208,6 +216,16 @@
         }
     }
 
+    private boolean shouldRingForContact(Uri contactUri) {
+        final NotificationManager manager =
+                (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+        final Bundle extras = new Bundle();
+        if (contactUri != null) {
+            extras.putStringArray(Notification.EXTRA_PEOPLE, new String[] {contactUri.toString()});
+        }
+        return manager.matchesCallFilter(extras);
+    }
+
     private void stopRinging() {
         Log.v(this, "stopRinging");
 
diff --git a/src/com/android/telecomm/TelecommServiceImpl.java b/src/com/android/telecomm/TelecommServiceImpl.java
index 9838036..ef26085 100644
--- a/src/com/android/telecomm/TelecommServiceImpl.java
+++ b/src/com/android/telecomm/TelecommServiceImpl.java
@@ -160,9 +160,9 @@
     //
 
     @Override
-    public PhoneAccountHandle getDefaultOutgoingPhoneAccount() {
+    public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme) {
         try {
-            return mPhoneAccountRegistrar.getDefaultOutgoingPhoneAccount();
+            return mPhoneAccountRegistrar.getDefaultOutgoingPhoneAccount(uriScheme);
         } catch (Exception e) {
             Log.e(this, e, "getDefaultOutgoingPhoneAccount");
             throw e;
@@ -192,6 +192,16 @@
     }
 
     @Override
+    public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme) {
+        try {
+            return mPhoneAccountRegistrar.getOutgoingPhoneAccounts(uriScheme);
+        } catch (Exception e) {
+            Log.e(this, e, "getPhoneAccountsSupportingScheme");
+            throw e;
+        }
+    }
+
+    @Override
     public PhoneAccount getPhoneAccount(PhoneAccountHandle accountHandle) {
         try {
             return mPhoneAccountRegistrar.getPhoneAccount(accountHandle);
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index d8877fb..8ae47d2 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -16,7 +16,8 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           coreApp="true"
-          package="com.android.telecomm.tests">
+          package="com.android.telecomm.tests"
+          android:debuggable="true">
 
     <!-- Test connection service outgoing video preview. -->
     <uses-permission android:name="android.permission.CAMERA" />
@@ -24,7 +25,8 @@
             android:name="com.android.telecomm.permission.REGISTER_PROVIDER_OR_SUBSCRIPTION" />
     <uses-permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE" />
 
-    <application android:label="@string/app_name">
+    <application android:label="@string/app_name"
+                 android:debuggable="true">
         <uses-library android:name="android.test.runner" />
 
         <!-- Miscellaneous telecomm app-related test activities. -->
@@ -116,5 +118,6 @@
     -->
     <instrumentation android:name="android.test.InstrumentationTestRunner"
             android:targetPackage="com.android.telecomm"
-            android:label="Telecomm application tests." />
+            android:label="Telecomm application tests."
+            android:debuggable="true"/>
 </manifest>
diff --git a/tests/src/com/android/telecomm/testapps/CallServiceNotifier.java b/tests/src/com/android/telecomm/testapps/CallServiceNotifier.java
index 5fd75e5..e8aa19f 100644
--- a/tests/src/com/android/telecomm/testapps/CallServiceNotifier.java
+++ b/tests/src/com/android/telecomm/testapps/CallServiceNotifier.java
@@ -109,6 +109,7 @@
                 .withIconResId(R.drawable.stat_sys_phone_call)
                 .withLabel("TelecommTestApp Call Provider")
                 .withShortDescription("a short description for the call provider")
+                .withSupportedUriScheme("tel")
                 .build());
 
         telecommManager.registerPhoneAccount(PhoneAccount.builder()
diff --git a/tests/src/com/android/telecomm/testapps/TestConnectionManager.java b/tests/src/com/android/telecomm/testapps/TestConnectionManager.java
index 95f0718..78c148d 100644
--- a/tests/src/com/android/telecomm/testapps/TestConnectionManager.java
+++ b/tests/src/com/android/telecomm/testapps/TestConnectionManager.java
@@ -95,12 +95,6 @@
             }
 
             @Override
-            public void onStartActivityFromInCall(
-                    RemoteConnection connection, PendingIntent intent) {
-                startActivityFromInCall(intent);
-            }
-
-            @Override
             public void onDestroyed(RemoteConnection connection) {
                 destroy();
                 mManagedConnectionByRemote.remove(mRemote);
diff --git a/tests/src/com/android/telecomm/tests/unit/PhoneAccountRegistrarTest.java b/tests/src/com/android/telecomm/tests/unit/PhoneAccountRegistrarTest.java
index 9daa026..3522153 100644
--- a/tests/src/com/android/telecomm/tests/unit/PhoneAccountRegistrarTest.java
+++ b/tests/src/com/android/telecomm/tests/unit/PhoneAccountRegistrarTest.java
@@ -24,6 +24,7 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import android.content.ComponentName;
+import android.content.Context;
 import android.net.Uri;
 import android.telecomm.PhoneAccount;
 import android.telecomm.PhoneAccountHandle;
@@ -35,6 +36,7 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.util.Arrays;
 
 public class PhoneAccountRegistrarTest extends AndroidTestCase {
 
@@ -61,7 +63,8 @@
                 .withSubscriptionNumber("555-1212")
                 .withCapabilities(
                         PhoneAccount.CAPABILITY_CALL_PROVIDER
-                                | PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
+                                | PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION
+                )
                 .withIconResId(0)
                 .withLabel("label1")
                 .withShortDescription("desc1")
@@ -86,6 +89,17 @@
                 .withLabel("label2")
                 .withShortDescription("desc2")
                 .build());
+        mRegistrar.registerPhoneAccount(PhoneAccount.builder()
+                .withAccountHandle(
+                        new PhoneAccountHandle(new ComponentName("sippkg", "sipcls"), "id4"))
+                .withHandle(Uri.parse("sip:test@sip.com"))
+                .withSubscriptionNumber("test")
+                .withCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+                .withIconResId(0)
+                .withLabel("label2")
+                .withShortDescription("desc2")
+                .withSupportedUriScheme("tel")
+                .build());
     }
 
     @Override
@@ -97,7 +111,8 @@
     private static <T> T roundTrip(
             Object self,
             T input,
-            PhoneAccountRegistrar.XmlSerialization<T> xml)
+            PhoneAccountRegistrar.XmlSerialization<T> xml,
+            Context context)
             throws Exception {
         Log.d(self, "Input = %s", input);
 
@@ -118,7 +133,7 @@
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(new BufferedInputStream(new ByteArrayInputStream(data)), null);
             parser.nextTag();
-            result = xml.readFromXml(parser);
+            result = xml.readFromXml(parser, 0, context);
         }
 
         Log.d(self, "result = " + result);
@@ -140,7 +155,8 @@
 
     public void testPhoneAccountHandle() throws Exception {
         PhoneAccountHandle input = new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), "id0");
-        PhoneAccountHandle result = roundTrip(this, input, PhoneAccountRegistrar.sPhoneAccountHandleXml);
+        PhoneAccountHandle result = roundTrip(this, input,
+                PhoneAccountRegistrar.sPhoneAccountHandleXml, mContext);
         assertPhoneAccountHandleEquals(input, result);
         PhoneAccountHandle inputN =
                 new PhoneAccountHandle(
@@ -148,7 +164,8 @@
                                 "pkg0",  // ctor does not allow null
                                 "cls0"), // ctor does not allow null
                         null);
-        PhoneAccountHandle resultN = roundTrip(this, inputN, PhoneAccountRegistrar.sPhoneAccountHandleXml);
+        PhoneAccountHandle resultN = roundTrip(this, inputN,
+                PhoneAccountRegistrar.sPhoneAccountHandleXml, mContext);
         Log.i(this, "inputN = %s, resultN = %s", inputN, resultN);
         assertPhoneAccountHandleEquals(inputN, resultN);
     }
@@ -162,15 +179,18 @@
             assertEquals(a.getIconResId(), b.getIconResId());
             assertEquals(a.getLabel(), b.getLabel());
             assertEquals(a.getShortDescription(), b.getShortDescription());
+            assertEquals(a.getSupportedUriSchemes(), b.getSupportedUriSchemes());
         }
     }
 
     public void testPhoneAccount() throws Exception {
         PhoneAccount input = makeQuickAccount("pkg0", "cls0", "id0", 0);
-        PhoneAccount result = roundTrip(this, input, PhoneAccountRegistrar.sPhoneAccountXml);
+        PhoneAccount result = roundTrip(this, input, PhoneAccountRegistrar.sPhoneAccountXml,
+                mContext);
         assertPhoneAccountEquals(input, result);
         PhoneAccount inputN = PhoneAccount.builder().build();
-        PhoneAccount resultN = roundTrip(this, inputN, PhoneAccountRegistrar.sPhoneAccountXml);
+        PhoneAccount resultN = roundTrip(this, inputN, PhoneAccountRegistrar.sPhoneAccountXml,
+                mContext);
         assertPhoneAccountEquals(inputN, resultN);
     }
 
@@ -185,7 +205,8 @@
 
     public void testState() throws Exception {
         PhoneAccountRegistrar.State input = makeQuickState();
-        PhoneAccountRegistrar.State result = roundTrip(this, input, PhoneAccountRegistrar.sStateXml);
+        PhoneAccountRegistrar.State result = roundTrip(this, input, PhoneAccountRegistrar.sStateXml,
+                mContext);
         assertStateEquals(input, result);
     }
 
@@ -193,7 +214,7 @@
         assertEquals(4, mRegistrar.getAllPhoneAccountHandles().size());
         assertEquals(3, mRegistrar.getOutgoingPhoneAccounts().size());
         assertEquals(null, mRegistrar.getSimCallManager());
-        assertEquals(null, mRegistrar.getDefaultOutgoingPhoneAccount());
+        assertEquals(null, mRegistrar.getDefaultOutgoingPhoneAccount("tel"));
     }
 
     public void testSimCallManager() throws Exception {
@@ -219,23 +240,23 @@
 
     public void testDefaultOutgoing() {
         // Establish initial conditions
-        assertEquals(null, mRegistrar.getDefaultOutgoingPhoneAccount());
+        assertEquals(null, mRegistrar.getDefaultOutgoingPhoneAccount("tel"));
         PhoneAccountHandle h = new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), "id1");
         mRegistrar.setDefaultOutgoingPhoneAccount(h);
-        assertPhoneAccountHandleEquals(h, mRegistrar.getDefaultOutgoingPhoneAccount());
+        assertPhoneAccountHandleEquals(h, mRegistrar.getDefaultOutgoingPhoneAccount("tel"));
         // If account is un-registered, querying returns null
         mRegistrar.unregisterPhoneAccount(h);
-        assertEquals(null, mRegistrar.getDefaultOutgoingPhoneAccount());
+        assertEquals(null, mRegistrar.getDefaultOutgoingPhoneAccount("tel"));
         // But if account is re-registered, setting comes back
         mRegistrar.registerPhoneAccount(makeQuickAccount("pkg0", "cls0", "id1", 99));
-        assertPhoneAccountHandleEquals(h, mRegistrar.getDefaultOutgoingPhoneAccount());
+        assertPhoneAccountHandleEquals(h, mRegistrar.getDefaultOutgoingPhoneAccount("tel"));
         // De-register by setting to null
         mRegistrar.setDefaultOutgoingPhoneAccount(null);
-        assertEquals(null, mRegistrar.getDefaultOutgoingPhoneAccount());
+        assertEquals(null, mRegistrar.getDefaultOutgoingPhoneAccount("tel"));
         // If argument not have CALL_PROVIDER capability, this is a no-op
         mRegistrar.setDefaultOutgoingPhoneAccount(
                 new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), "id0"));
-        assertEquals(null, mRegistrar.getDefaultOutgoingPhoneAccount());
+        assertEquals(null, mRegistrar.getDefaultOutgoingPhoneAccount("tel"));
         // If only have one account, it is the default
         mRegistrar.unregisterPhoneAccount(
                 new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), "id0"));
@@ -245,7 +266,7 @@
                 new PhoneAccountHandle(new ComponentName("pkg1", "cls1"), "id2"));
         assertPhoneAccountHandleEquals(
                 new PhoneAccountHandle(new ComponentName("pkg1", "cls1"), "id3"),
-                mRegistrar.getDefaultOutgoingPhoneAccount());
+                mRegistrar.getDefaultOutgoingPhoneAccount("tel"));
         // If have one account but not suitable, default returns null
         mRegistrar.unregisterPhoneAccount(
                 new PhoneAccountHandle(new ComponentName("pkg1", "cls1"), "id3"));
@@ -258,7 +279,7 @@
                 .withLabel("label0")
                 .withShortDescription("desc0")
                 .build());
-        assertEquals(null, mRegistrar.getDefaultOutgoingPhoneAccount());
+        assertEquals(null, mRegistrar.getDefaultOutgoingPhoneAccount("tel"));
     }
 
     private static PhoneAccount makeQuickAccount(String pkg, String cls, String id, int idx) {