Add emergency SUPL DDS switch for DP only roaming partners

Although an operator may support control plane fallback for
emergency SUPL requests, a roaming operator may not. Define
a new CarrierConfig for known roaming partners of an operator
that do not support CP fallback and in those cases, perform
a DDS switch before placing the emergency call if possible.

Bug: 144383368
Test: manual; atest TeleServiceTests
Change-Id: I7bd81ddb9730cd2cff7c246f0321af090eb6b2c6
diff --git a/tests/Android.bp b/tests/Android.bp
index 42d88eb..de44863 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -20,6 +20,7 @@
     srcs: ["src/**/*.java"],
 
     libs: [
+        "android.test.mock",
         "android.test.runner",
         "telephony-common",
         "android.test.base",
diff --git a/tests/src/com/android/TelephonyTestBase.java b/tests/src/com/android/TelephonyTestBase.java
index d30ae6b..01267d8 100644
--- a/tests/src/com/android/TelephonyTestBase.java
+++ b/tests/src/com/android/TelephonyTestBase.java
@@ -16,13 +16,10 @@
 
 package com.android;
 
-import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
 import android.util.Log;
 
-import androidx.test.InstrumentationRegistry;
-
 import org.mockito.MockitoAnnotations;
 
 import java.util.concurrent.CountDownLatch;
@@ -33,11 +30,11 @@
  */
 public class TelephonyTestBase {
 
-    protected Context mContext;
+    protected TestContext mContext;
 
     public void setUp() throws Exception {
-        mContext = InstrumentationRegistry.getTargetContext();
         MockitoAnnotations.initMocks(this);
+        mContext = new TestContext();
         // Set up the looper if it does not exist on the test thread.
         if (Looper.myLooper() == null) {
             Looper.prepare();
@@ -86,4 +83,8 @@
             Log.e("TelephonyTestBase", "InterruptedException while waiting: " + e);
         }
     }
+
+    protected TestContext getTestContext() {
+        return mContext;
+    }
 }
diff --git a/tests/src/com/android/TestContext.java b/tests/src/com/android/TestContext.java
new file mode 100644
index 0000000..f4ce494
--- /dev/null
+++ b/tests/src/com/android/TestContext.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2019 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;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.PersistableBundle;
+import android.telecom.TelecomManager;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.test.mock.MockContext;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class TestContext extends MockContext {
+
+    @Mock CarrierConfigManager mMockCarrierConfigManager;
+    @Mock TelecomManager mMockTelecomManager;
+    @Mock TelephonyManager mMockTelephonyManager;
+    @Mock SubscriptionManager mMockSubscriptionManager;
+
+    private PersistableBundle mCarrierConfig = new PersistableBundle();
+
+    public TestContext() {
+        MockitoAnnotations.initMocks(this);
+        doReturn(mCarrierConfig).when(mMockCarrierConfigManager).getConfigForSubId(anyInt());
+    }
+
+    @Override
+    public Context getApplicationContext() {
+        return this;
+    }
+
+    @Override
+    public String getPackageName() {
+        return "com.android.phone.tests";
+    }
+
+    @Override
+    public String getFeatureId() {
+        return "";
+    }
+
+    @Override
+    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
+        return null;
+    }
+
+    @Override
+    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, int flags) {
+        return null;
+    }
+
+    @Override
+    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
+            String broadcastPermission, Handler scheduler) {
+        return null;
+    }
+
+    @Override
+    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
+            String broadcastPermission, Handler scheduler, int flags) {
+        return null;
+    }
+
+    @Override
+    public Object getSystemService(String name) {
+        switch (name) {
+            case (Context.CARRIER_CONFIG_SERVICE) : {
+                return mMockCarrierConfigManager;
+            }
+            case (Context.TELECOM_SERVICE) : {
+                return mMockTelecomManager;
+            }
+            case (Context.TELEPHONY_SERVICE) : {
+                return mMockTelephonyManager;
+            }
+            case (Context.TELEPHONY_SUBSCRIPTION_SERVICE) : {
+                return mMockSubscriptionManager;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String getSystemServiceName(Class<?> serviceClass) {
+        if (serviceClass == CarrierConfigManager.class) {
+            return Context.CARRIER_CONFIG_SERVICE;
+        }
+        if (serviceClass == TelecomManager.class) {
+            return Context.TELECOM_SERVICE;
+        }
+        if (serviceClass == TelephonyManager.class) {
+            return Context.TELEPHONY_SERVICE;
+        }
+        if (serviceClass == SubscriptionManager.class) {
+            return Context.TELEPHONY_SUBSCRIPTION_SERVICE;
+        }
+        return null;
+    }
+
+    public PersistableBundle getCarrierConfig() {
+        return mCarrierConfig;
+    }
+}
diff --git a/tests/src/com/android/phone/CallFeaturesSettingTest.java b/tests/src/com/android/phone/CallFeaturesSettingTest.java
index 8f49b97..7c7d6f8 100644
--- a/tests/src/com/android/phone/CallFeaturesSettingTest.java
+++ b/tests/src/com/android/phone/CallFeaturesSettingTest.java
@@ -36,6 +36,7 @@
 import com.android.internal.telephony.PhoneConstants;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.Mock;
@@ -62,6 +63,7 @@
         keepScreenOn(mRule, mActivity);
     }
 
+    @Ignore
     @FlakyTest
     @Test
     public void onResume_fdnIsAvailable_shouldShowFdnMenu() throws NoSuchFieldException,
@@ -77,6 +79,7 @@
         onView(withText(R.string.fdn)).check(matches(isDisplayed()));
     }
 
+    @Ignore
     @FlakyTest
     @Test
     public void onResume_iccCardIsNull_shouldNotShowFdnMenu() throws NoSuchFieldException,
@@ -91,6 +94,7 @@
         onView(withText(R.string.fdn)).check(doesNotExist());
     }
 
+    @Ignore
     @FlakyTest
     @Test
     public void onResume_fdnIsNotAvailable_shouldNotShowFdnMenu() throws NoSuchFieldException,
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index 166f2fb..cd7a580 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -17,10 +17,13 @@
 package com.android.services.telephony;
 
 import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.fail;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doReturn;
@@ -29,38 +32,45 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.ComponentName;
 import android.content.Context;
 import android.net.Uri;
 import android.os.AsyncResult;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.telecom.ConnectionRequest;
 import android.telecom.DisconnectCause;
+import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
+import android.telephony.CarrierConfigManager;
 import android.telephony.RadioAccessFamily;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
+import android.telephony.emergency.EmergencyNumber;
 import android.test.suitebuilder.annotation.SmallTest;
 
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.FlakyTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.TelephonyTestBase;
 import com.android.internal.telephony.CallStateException;
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneSwitcher;
 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
 import com.android.internal.telephony.gsm.SuppServiceNotification;
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 
 /**
@@ -74,20 +84,72 @@
     private static final int SLOT_0_PHONE_ID = 0;
     private static final int SLOT_1_PHONE_ID = 1;
 
+    private static final ComponentName TEST_COMPONENT_NAME = new ComponentName(
+            "com.android.phone.tests", TelephonyConnectionServiceTest.class.getName());
+    private static final String TEST_ACCOUNT_ID1 = "id1";
+    private static final String TEST_ACCOUNT_ID2 = "id2";
+    private static final PhoneAccountHandle PHONE_ACCOUNT_HANDLE_1 = new PhoneAccountHandle(
+            TEST_COMPONENT_NAME, TEST_ACCOUNT_ID1);
+    private static final PhoneAccountHandle PHONE_ACCOUNT_HANDLE_2 = new PhoneAccountHandle(
+            TEST_COMPONENT_NAME, TEST_ACCOUNT_ID2);
+    private static final Uri TEST_ADDRESS = Uri.parse("tel:+16505551212");
+
     @Mock TelephonyConnectionService.TelephonyManagerProxy mTelephonyManagerProxy;
     @Mock TelephonyConnectionService.SubscriptionManagerProxy mSubscriptionManagerProxy;
     @Mock TelephonyConnectionService.PhoneFactoryProxy mPhoneFactoryProxy;
+    @Mock DeviceState mDeviceState;
+    @Mock TelephonyConnectionService.PhoneSwitcherProxy mPhoneSwitcherProxy;
+    @Mock TelephonyConnectionService.PhoneNumberUtilsProxy mPhoneNumberUtilsProxy;
+    @Mock TelephonyConnectionService.PhoneUtilsProxy mPhoneUtilsProxy;
+    @Mock TelephonyConnectionService.HandlerFactory mHandlerFactory;
+    @Mock TelephonyConnectionService.DisconnectCauseFactory mDisconnectCauseFactory;
+    @Mock Handler mMockHandler;
     @Mock EmergencyNumberTracker mEmergencyNumberTracker;
+    @Mock PhoneSwitcher mPhoneSwitcher;
 
-    TelephonyConnectionService mTestConnectionService;
+    private static class TestTelephonyConnectionService extends TelephonyConnectionService {
+
+        private final Context mContext;
+
+        TestTelephonyConnectionService(Context context) {
+            mContext = context;
+        }
+
+        @Override
+        public void onCreate() {
+            // attach test context.
+            attachBaseContext(mContext);
+            super.onCreate();
+        }
+    }
+
+    private TelephonyConnectionService mTestConnectionService;
 
     @Before
     public void setUp() throws Exception {
         super.setUp();
-        mTestConnectionService = new TelephonyConnectionService();
+        mTestConnectionService = new TestTelephonyConnectionService(mContext);
         mTestConnectionService.setPhoneFactoryProxy(mPhoneFactoryProxy);
-        mTestConnectionService.setTelephonyManagerProxy(mTelephonyManagerProxy);
         mTestConnectionService.setSubscriptionManagerProxy(mSubscriptionManagerProxy);
+        // Set configurations statically
+        doReturn(false).when(mDeviceState).shouldCheckSimStateBeforeOutgoingCall(any());
+        mTestConnectionService.setPhoneSwitcherProxy(mPhoneSwitcherProxy);
+        doReturn(mPhoneSwitcher).when(mPhoneSwitcherProxy).getPhoneSwitcher();
+        mTestConnectionService.setPhoneNumberUtilsProxy(mPhoneNumberUtilsProxy);
+        mTestConnectionService.setPhoneUtilsProxy(mPhoneUtilsProxy);
+        HandlerThread mockHandlerThread = mock(HandlerThread.class);
+        doReturn(mockHandlerThread).when(mHandlerFactory).createHandlerThread(anyString());
+        doReturn(null).when(mockHandlerThread).getLooper();
+        doReturn(mMockHandler).when(mHandlerFactory).createHandler(any());
+        mTestConnectionService.setHandlerFactory(mHandlerFactory);
+        mTestConnectionService.setDeviceState(mDeviceState);
+        doReturn(new DisconnectCause(DisconnectCause.UNKNOWN)).when(mDisconnectCauseFactory)
+                .toTelecomDisconnectCause(anyInt(), any());
+        doReturn(new DisconnectCause(DisconnectCause.UNKNOWN)).when(mDisconnectCauseFactory)
+                .toTelecomDisconnectCause(anyInt(), any(), anyInt());
+        mTestConnectionService.setDisconnectCauseFactory(mDisconnectCauseFactory);
+        mTestConnectionService.onCreate();
+        mTestConnectionService.setTelephonyManagerProxy(mTelephonyManagerProxy);
     }
 
     @After
@@ -103,7 +165,6 @@
      *
      * Result: getFirstPhoneForEmergencyCall returns the default Voice SIM choice.
      */
-    @Ignore
     @Test
     @SmallTest
     public void testDefaultVoiceSimInService() {
@@ -126,7 +187,6 @@
      *
      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone
      */
-    @Ignore
     @Test
     @SmallTest
     public void testSlot1EmergencyOnly() {
@@ -149,7 +209,6 @@
      *
      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone
      */
-    @Ignore
     @Test
     @SmallTest
     public void testSlot1InService() {
@@ -174,7 +233,6 @@
      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone. Although Slot 0 is more
      * capable, it is locked, so use the other slot.
      */
-    @Ignore
     @Test
     @SmallTest
     public void testSlot0PukLocked() {
@@ -205,7 +263,6 @@
      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone. Although Slot 0 is more
      * capable, it is locked, so use the other slot.
      */
-    @Ignore
     @Test
     @SmallTest
     public void testSlot0PinLocked() {
@@ -236,7 +293,6 @@
      * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone. Although Slot 1 is more
      * capable, it is locked, so use the other slot.
      */
-    @Ignore
     @Test
     @SmallTest
     public void testSlot1PukLocked() {
@@ -267,7 +323,6 @@
      * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone. Although Slot 1 is more
      * capable, it is locked, so use the other slot.
      */
-    @Ignore
     @Test
     @SmallTest
     public void testSlot1PinLocked() {
@@ -297,7 +352,6 @@
      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it is the only one
      * with a SIM inserted (even if it is PUK locked)
      */
-    @Ignore
     @Test
     @SmallTest
     public void testSlot1PinLockedAndSlot0Absent() {
@@ -328,7 +382,6 @@
      *
      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it is more capable
      */
-    @Ignore
     @Test
     @SmallTest
     public void testSlot1HigherCapablity() {
@@ -357,7 +410,6 @@
      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it has more
      * capabilities.
      */
-    @Ignore
     @Test
     @SmallTest
     public void testSlot1MoreCapabilities() {
@@ -388,7 +440,6 @@
      * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone because it is more capable,
      * ignoring that both SIMs are PUK locked.
      */
-    @Ignore
     @Test
     @SmallTest
     public void testSlot0MoreCapableBothPukLocked() {
@@ -416,7 +467,6 @@
      *
      * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone because it is the first slot.
      */
-    @Ignore
     @Test
     @SmallTest
     public void testEqualCapabilityTwoSimsInserted() {
@@ -448,7 +498,6 @@
      * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone because it is the only one
      * with a SIM inserted
      */
-    @Ignore
     @Test
     @SmallTest
     public void testEqualCapabilitySim0Inserted() {
@@ -480,7 +529,6 @@
      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it is the only one
      * with a SIM inserted
      */
-    @Ignore
     @Test
     @SmallTest
     public void testEqualCapabilitySim1Inserted() {
@@ -512,7 +560,6 @@
      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone, since it is a higher
      * capability
      */
-    @Ignore
     @Test
     @SmallTest
     public void testSim1HigherCapabilityNoSimsInserted() {
@@ -543,7 +590,6 @@
      *
      * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone, since it is the first slot.
      */
-    @Ignore
     @Test
     @SmallTest
     public void testEqualCapabilityNoSimsInserted() {
@@ -574,9 +620,7 @@
      * Verify that dial is called on the same phone again when retryOutgoingOriginalConnection is
      * called.
      */
-    @Ignore
     @Test
-    @FlakyTest
     @SmallTest
     public void testRetryOutgoingOriginalConnection_redialTempFailOneSlot() {
         TestTelephonyConnection c = new TestTelephonyConnection();
@@ -585,7 +629,7 @@
         List<Phone> phones = new ArrayList<>(1);
         phones.add(slot0Phone);
         setPhones(phones);
-        c.setAddress(Uri.parse("tel:+16505551212"), TelecomManager.PRESENTATION_ALLOWED);
+        c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
 
         mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/);
 
@@ -607,9 +651,8 @@
      * Verify that the connection is set to disconnected with an error disconnect cause and dial is
      * not called.
      */
-    @Ignore
+
     @Test
-    @FlakyTest
     @SmallTest
     public void testRetryOutgoingOriginalConnection_redialPermFailOneSlot() {
         TestTelephonyConnection c = new TestTelephonyConnection();
@@ -618,7 +661,7 @@
         List<Phone> phones = new ArrayList<>(1);
         phones.add(slot0Phone);
         setPhones(phones);
-        c.setAddress(Uri.parse("tel:+16505551212"), TelecomManager.PRESENTATION_ALLOWED);
+        c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
 
         mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/);
 
@@ -642,9 +685,7 @@
      * Verify that the emergency call is dialed on the other slot and telecom is notified of the new
      * PhoneAccount.
      */
-    @Ignore
     @Test
-    @FlakyTest
     @SmallTest
     public void testRetryOutgoingOriginalConnection_redialTempFailTwoSlot() {
         TestTelephonyConnection c = new TestTelephonyConnection();
@@ -653,11 +694,15 @@
         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
                 false /*isEmergencyOnly*/);
         setPhonesDialConnection(slot1Phone, c.getOriginalConnection());
-        c.setAddress(Uri.parse("tel:+16505551212"), TelecomManager.PRESENTATION_ALLOWED);
+        c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
         List<Phone> phones = new ArrayList<>(2);
         phones.add(slot0Phone);
         phones.add(slot1Phone);
         setPhones(phones);
+        doReturn(PHONE_ACCOUNT_HANDLE_1).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
+                slot0Phone);
+        doReturn(PHONE_ACCOUNT_HANDLE_2).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
+                slot1Phone);
 
         mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/);
 
@@ -681,9 +726,7 @@
      * Verify that the emergency call is dialed on the other slot and telecom is notified of the new
      * PhoneAccount.
      */
-    @Ignore
     @Test
-    @FlakyTest
     @SmallTest
     public void testRetryOutgoingOriginalConnection_redialPermFailTwoSlot() {
         TestTelephonyConnection c = new TestTelephonyConnection();
@@ -692,11 +735,15 @@
         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
                 false /*isEmergencyOnly*/);
         setPhonesDialConnection(slot1Phone, c.getOriginalConnection());
-        c.setAddress(Uri.parse("tel:+16505551212"), TelecomManager.PRESENTATION_ALLOWED);
+        c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
         List<Phone> phones = new ArrayList<>(2);
         phones.add(slot0Phone);
         phones.add(slot1Phone);
         setPhones(phones);
+        doReturn(PHONE_ACCOUNT_HANDLE_1).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
+                slot0Phone);
+        doReturn(PHONE_ACCOUNT_HANDLE_2).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
+                slot1Phone);
 
         mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/);
 
@@ -720,9 +767,7 @@
      * Verify that the emergency call is dialed on slot 1 and then on slot 0 and telecom is
      * notified of this twice.
      */
-    @Ignore
     @Test
-    @FlakyTest
     @SmallTest
     public void testRetryOutgoingOriginalConnection_redialTempFailTwoSlot_twoFailure() {
         TestTelephonyConnection c = new TestTelephonyConnection();
@@ -731,11 +776,15 @@
         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
                 false /*isEmergencyOnly*/);
         setPhonesDialConnection(slot1Phone, c.getOriginalConnection());
-        c.setAddress(Uri.parse("tel:+16505551212"), TelecomManager.PRESENTATION_ALLOWED);
+        c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
         List<Phone> phones = new ArrayList<>(2);
         phones.add(slot0Phone);
         phones.add(slot1Phone);
         setPhones(phones);
+        doReturn(PHONE_ACCOUNT_HANDLE_1).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
+                slot0Phone);
+        doReturn(PHONE_ACCOUNT_HANDLE_2).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
+                slot1Phone);
 
         // First Temporary failure
         mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/);
@@ -773,9 +822,7 @@
      * Verify that the emergency call is dialed on slot 1 and then disconnected and telecom is
      * notified of the change to slot 1.
      */
-    @Ignore
     @Test
-    @FlakyTest
     @SmallTest
     public void testRetryOutgoingOriginalConnection_redialPermFailTwoSlot_twoFailure() {
         TestTelephonyConnection c = new TestTelephonyConnection();
@@ -784,11 +831,15 @@
         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
                 false /*isEmergencyOnly*/);
         setPhonesDialConnection(slot1Phone, c.getOriginalConnection());
-        c.setAddress(Uri.parse("tel:+16505551212"), TelecomManager.PRESENTATION_ALLOWED);
+        c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
         List<Phone> phones = new ArrayList<>(2);
         phones.add(slot0Phone);
         phones.add(slot1Phone);
         setPhones(phones);
+        doReturn(PHONE_ACCOUNT_HANDLE_1).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
+                slot0Phone);
+        doReturn(PHONE_ACCOUNT_HANDLE_2).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
+                slot1Phone);
 
         // First Permanent failure
         mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/);
@@ -817,7 +868,6 @@
         }
     }
 
-    @Ignore
     @Test
     @SmallTest
     public void testSuppServiceNotification() {
@@ -827,11 +877,7 @@
         // registration to occur.
         Phone phone = c.getPhone();
         c.setOriginalConnection(c.getOriginalConnection());
-
-        // Use a real context since the method SubscriptionManager.getResourcesForSubId()
-        // needs to interact with a real context.
-        Context targetContext = InstrumentationRegistry.getTargetContext();
-        doReturn(targetContext).when(phone).getContext();
+        doReturn(mContext).when(phone).getContext();
 
         // When the registration occurs, we'll capture the handler and message so we can post our
         // own messages to it.
@@ -868,6 +914,239 @@
                 extras.getInt(TelephonyManager.EXTRA_NOTIFICATION_CODE));
     }
 
+    /**
+     * Test that the TelephonyConnectionService successfully performs a DDS switch before a call
+     * when we are not roaming and the carrier only supports SUPL over the data plane.
+     */
+    @Test
+    @SmallTest
+    public void testCreateOutgoingEmergencyConnection_delayDial_carrierconfig_dds() {
+        Phone testPhone = setupConnectionServiceForDelayDial();
+        Runnable delayDialRunnable = verifyRunnablePosted();
+
+        // Setup test to not support SUPL on the non-DDS subscription
+        doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
+        getTestContext().getCarrierConfig().putStringArray(
+                CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
+                null);
+        testPhone.getServiceState().setRoaming(false);
+        getTestContext().getCarrierConfig().putInt(
+                CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
+                CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY);
+        getTestContext().getCarrierConfig().putString(
+                CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "150");
+        delayDialRunnable.run();
+
+        verify(mPhoneSwitcher).overrideDefaultDataForEmergency(eq(0) /*phoneId*/ ,
+                eq(150) /*extensionTime*/, any());
+    }
+
+    /**
+     * Test that the TelephonyConnectionService does not perform a DDS switch when the carrier
+     * supports control-plane fallback.
+     */
+    @Test
+    @SmallTest
+    public void testCreateOutgoingEmergencyConnection_delayDial_nocarrierconfig() {
+        Phone testPhone = setupConnectionServiceForDelayDial();
+        Runnable delayDialRunnable = verifyRunnablePosted();
+
+        // Setup test to not support SUPL on the non-DDS subscription
+        doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
+        getTestContext().getCarrierConfig().putStringArray(
+                CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
+                null);
+        testPhone.getServiceState().setRoaming(false);
+        getTestContext().getCarrierConfig().putInt(
+                CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
+                CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK);
+        getTestContext().getCarrierConfig().putString(
+                CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
+        delayDialRunnable.run();
+
+        verify(mPhoneSwitcher, never()).overrideDefaultDataForEmergency(anyInt(), anyInt(), any());
+    }
+
+    /**
+     * Test that the TelephonyConnectionService does not perform a DDS switch when the carrier
+     * supports control-plane fallback.
+     */
+    @Test
+    @SmallTest
+    public void testCreateOutgoingEmergencyConnection_delayDial_supportsuplondds() {
+        Phone testPhone = setupConnectionServiceForDelayDial();
+        Runnable delayDialRunnable = verifyRunnablePosted();
+
+        // If the non-DDS supports SUPL, dont switch data
+        doReturn(false).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
+        getTestContext().getCarrierConfig().putStringArray(
+                CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
+                null);
+        testPhone.getServiceState().setRoaming(false);
+        getTestContext().getCarrierConfig().putInt(
+                CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
+                CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY);
+        getTestContext().getCarrierConfig().putString(
+                CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
+        delayDialRunnable.run();
+
+        verify(mPhoneSwitcher, never()).overrideDefaultDataForEmergency(anyInt(), anyInt(), any());
+    }
+
+    /**
+     * Test that the TelephonyConnectionService does not perform a DDS switch when the carrier does
+     * not support control-plane fallback CarrierConfig while roaming.
+     */
+    @Test
+    @SmallTest
+    public void testCreateOutgoingEmergencyConnection_delayDial_roaming_nocarrierconfig() {
+        Phone testPhone = setupConnectionServiceForDelayDial();
+        Runnable delayDialRunnable = verifyRunnablePosted();
+
+        // Setup test to not support SUPL on the non-DDS subscription
+        doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
+        getTestContext().getCarrierConfig().putStringArray(
+                CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
+                null);
+        testPhone.getServiceState().setRoaming(true);
+        getTestContext().getCarrierConfig().putInt(
+                CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
+                CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY);
+        getTestContext().getCarrierConfig().putString(
+                CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
+        delayDialRunnable.run();
+
+        verify(mPhoneSwitcher, never()).overrideDefaultDataForEmergency(anyInt(), anyInt(), any());
+    }
+
+    /**
+     * Test that the TelephonyConnectionService does perform a DDS switch even though the carrier
+     * supports control-plane fallback CarrierConfig and the roaming partner is configured to look
+     * like a home network.
+     */
+    @Test
+    @SmallTest
+    public void testCreateOutgoingEmergencyConnection_delayDial_roamingcarrierconfig() {
+        Phone testPhone = setupConnectionServiceForDelayDial();
+        Runnable delayDialRunnable = verifyRunnablePosted();
+
+        // Setup voice roaming scenario
+        String testRoamingOperator = "001001";
+        // In some roaming conditions, we are not technically "roaming"
+        testPhone.getServiceState().setRoaming(false);
+        testPhone.getServiceState().setOperatorName("TestTel", "TestTel", testRoamingOperator);
+        // Setup test to not support SUPL on the non-DDS subscription
+        doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
+        String[] roamingPlmns = new String[1];
+        roamingPlmns[0] = testRoamingOperator;
+        getTestContext().getCarrierConfig().putStringArray(
+                CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
+                roamingPlmns);
+        getTestContext().getCarrierConfig().putInt(
+                CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
+                CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK);
+        getTestContext().getCarrierConfig().putString(
+                CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
+        delayDialRunnable.run();
+
+        verify(mPhoneSwitcher).overrideDefaultDataForEmergency(eq(0) /*phoneId*/ ,
+                eq(0) /*extensionTime*/, any());
+    }
+
+    /**
+     * Test that the TelephonyConnectionService does perform a DDS switch even though the carrier
+     * supports control-plane fallback CarrierConfig if we are roaming and the roaming partner is
+     * configured to use data plane only SUPL.
+     */
+    @Test
+    @SmallTest
+    public void testCreateOutgoingEmergencyConnection_delayDial__roaming_roamingcarrierconfig() {
+        Phone testPhone = setupConnectionServiceForDelayDial();
+        Runnable delayDialRunnable = verifyRunnablePosted();
+
+        // Setup voice roaming scenario
+        String testRoamingOperator = "001001";
+        testPhone.getServiceState().setRoaming(true);
+        testPhone.getServiceState().setOperatorName("TestTel", "TestTel", testRoamingOperator);
+        // Setup test to not support SUPL on the non-DDS subscription
+        doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
+        String[] roamingPlmns = new String[1];
+        roamingPlmns[0] = testRoamingOperator;
+        getTestContext().getCarrierConfig().putStringArray(
+                CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
+                roamingPlmns);
+        getTestContext().getCarrierConfig().putInt(
+                CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
+                CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK);
+        getTestContext().getCarrierConfig().putString(
+                CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
+        delayDialRunnable.run();
+
+        verify(mPhoneSwitcher).overrideDefaultDataForEmergency(eq(0) /*phoneId*/ ,
+                eq(0) /*extensionTime*/, any());
+    }
+
+    /**
+     * Set up a mock MSIM device with TEST_ADDRESS set as an emergency number.
+     * @return the Phone associated with slot 0.
+     */
+    private Phone setupConnectionServiceForDelayDial() {
+        ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
+                .setAccountHandle(PHONE_ACCOUNT_HANDLE_1)
+                .setAddress(TEST_ADDRESS)
+                .build();
+        Phone testPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_IN_SERVICE,
+                false /*isEmergencyOnly*/);
+        Phone testPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_OUT_OF_SERVICE,
+                false /*isEmergencyOnly*/);
+        List<Phone> phones = new ArrayList<>(2);
+        doReturn(true).when(testPhone0).isRadioOn();
+        doReturn(true).when(testPhone1).isRadioOn();
+        phones.add(testPhone0);
+        phones.add(testPhone1);
+        setPhones(phones);
+        setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_1, testPhone0);
+        setupDeviceConfig(testPhone0, testPhone1, 1);
+        doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(
+                TEST_ADDRESS.getSchemeSpecificPart());
+        HashMap<Integer, List<EmergencyNumber>> emergencyNumbers = new HashMap<>(1);
+        List<EmergencyNumber> numbers = new ArrayList<>();
+        numbers.add(setupEmergencyNumber(TEST_ADDRESS));
+        emergencyNumbers.put(0 /*subId*/, numbers);
+        doReturn(emergencyNumbers).when(mTelephonyManagerProxy).getCurrentEmergencyNumberList();
+        doReturn(2).when(mTelephonyManagerProxy).getPhoneCount();
+
+        android.telecom.Connection testConnection = mTestConnectionService
+                .onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1, connectionRequest);
+        assertNotNull("test connection was not set up correctly.", testConnection);
+
+        return testPhone0;
+    }
+
+    private Runnable verifyRunnablePosted() {
+        ArgumentCaptor<Message> runnableCaptor = ArgumentCaptor.forClass(Message.class);
+        verify(mMockHandler).sendMessageDelayed(runnableCaptor.capture(), anyLong());
+        assertNotNull("Invalid Message created", runnableCaptor.getValue());
+        Runnable runnable = runnableCaptor.getValue().getCallback();
+        assertNotNull("sendMessageDelayed never occurred.", runnableCaptor);
+        return runnable;
+    }
+
+    private EmergencyNumber setupEmergencyNumber(Uri address) {
+        return new EmergencyNumber(address.getSchemeSpecificPart(), "", "",
+        EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
+        Collections.emptyList(),
+        EmergencyNumber.EMERGENCY_NUMBER_SOURCE_SIM,
+        EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY);
+    }
+
+    private void setupHandleToPhoneMap(PhoneAccountHandle handle,  Phone phone) {
+        // use subId 0
+        when(mPhoneUtilsProxy.getSubIdForPhoneAccountHandle(handle)).thenReturn(0);
+        when(mSubscriptionManagerProxy.getPhoneId(0)).thenReturn(0);
+        when(mPhoneFactoryProxy.getPhone(0)).thenReturn(phone);
+    }
+
     private AsyncResult getSuppServiceNotification(int notificationType, int code) {
         SuppServiceNotification notification = new SuppServiceNotification();
         notification.notificationType = notificationType;
@@ -880,6 +1159,7 @@
         ServiceState testServiceState = new ServiceState();
         testServiceState.setState(serviceState);
         testServiceState.setEmergencyOnly(isEmergencyOnly);
+        when(phone.getContext()).thenReturn(mContext);
         when(phone.getServiceState()).thenReturn(testServiceState);
         when(phone.getPhoneId()).thenReturn(phoneId);
         when(phone.getDefaultPhone()).thenReturn(phone);
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionTest.java
index 6feefec..cfc0ccc 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionTest.java
@@ -7,14 +7,12 @@
 
 import androidx.test.runner.AndroidJUnit4;
 
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
 public class TelephonyConnectionTest {
 
-    @Ignore
     @Test
     public void testCodecInIms() {
         TestTelephonyConnection c = new TestTelephonyConnection();
diff --git a/tests/src/com/android/services/telephony/TestTelephonyConnection.java b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
index 593494b..5b31c0f 100644
--- a/tests/src/com/android/services/telephony/TestTelephonyConnection.java
+++ b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Bundle;
+import android.os.PersistableBundle;
 import android.telecom.PhoneAccountHandle;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -135,6 +136,28 @@
         // Do nothing since the original connection is mock object
     }
 
+    @Override
+    public PersistableBundle getCarrierConfig() {
+        // Depends on PhoneGlobals for context in TelephonyConnection, do not implement during
+        // testing.
+        return new PersistableBundle();
+    }
+
+    @Override
+    public CharSequence getResourceText(int messageId) {
+        return "TEST";
+    }
+
+    @Override
+    public String getResourceString(int id) {
+        return "TEST";
+    }
+
+    @Override
+    void refreshConferenceSupported() {
+        // Requires ImsManager dependencies, do not implement during testing.
+    }
+
     public int getNotifyPhoneAccountChangedCount() {
         return mNotifyPhoneAccountChangedCount;
     }