Add supported URI scheme to PhoneAccounts. (2/4)

Modify PhoneAccountRegistrar to load/save supported URI schemes to
the state XML file.
Added version check to state XML file and migration step to add
'sip' for SIPConnectionService PhoneAccounts, and 'tel' for all other
PhoneAccounts.

Bug: 17140110
Change-Id: Ic5d41254bade421cc39eb197a1d6fc2d6695f62f
diff --git a/src/com/android/telecomm/CallsManager.java b/src/com/android/telecomm/CallsManager.java
index 8935766..a7fb313 100644
--- a/src/com/android/telecomm/CallsManager.java
+++ b/src/com/android/telecomm/CallsManager.java
@@ -307,9 +307,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/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/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/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/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) {