Merge "Removed permission check"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 258ec1c..9e56ef8 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -211,6 +211,7 @@
          ACTION_SIM_SLOT_STATUS_CHANGED broadcast to start activities
          from the background.  -->
     <uses-permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND" />
+    <uses-permission android:name="android.permission.NETWORK_STATS_PROVIDER" />
 
     <application android:name="PhoneApp"
             android:persistent="true"
diff --git a/OWNERS b/OWNERS
index 849347f..3059d4d 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,15 +1,15 @@
 amitmahajan@google.com
 breadley@google.com
 fionaxu@google.com
-hallliu@google.com
 jackyu@google.com
+hallliu@google.com
 rgreenwalt@google.com
 tgunn@google.com
-refuhoo@google.com
-mpq@google.com
 jminjie@google.com
 shuoq@google.com
-paulye@google.com
+refuhoo@google.com
 nazaninb@google.com
 sarahchin@google.com
 dbright@google.com
+xiaotonj@google.com
+
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 8098a61..a816c89 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -619,7 +619,6 @@
     private void broadcastConfigChangedIntent(int phoneId, boolean addSubIdExtra) {
         Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
-                Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND |
                 Intent.FLAG_RECEIVER_FOREGROUND);
         if (addSubIdExtra) {
             int simApplicationState = TelephonyManager.SIM_STATE_UNKNOWN;
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index c0b8617..92b063a 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -5702,14 +5702,13 @@
         }
     }
 
-    private int getCarrierPrivilegeStatusFromCarrierConfigRules(int privilegeFromSim,
+    private int getCarrierPrivilegeStatusFromCarrierConfigRules(int privilegeFromSim, int uid,
             Phone phone) {
         //load access rules from carrier configs, and check those as well: b/139133814
         SubscriptionController subController = SubscriptionController.getInstance();
         if (privilegeFromSim == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
                 || subController == null) return privilegeFromSim;
 
-        int uid = Binder.getCallingUid();
         PackageManager pkgMgr = phone.getContext().getPackageManager();
         String[] packages = pkgMgr.getPackagesForUid(uid);
 
@@ -5763,7 +5762,7 @@
 
         return getCarrierPrivilegeStatusFromCarrierConfigRules(
             card.getCarrierPrivilegeStatusForCurrentTransaction(
-                phone.getContext().getPackageManager()), phone);
+                phone.getContext().getPackageManager()), Binder.getCallingUid(), phone);
     }
 
     @Override
@@ -5782,7 +5781,7 @@
         }
         return getCarrierPrivilegeStatusFromCarrierConfigRules(
                 profile.getCarrierPrivilegeStatusForUid(
-                        phone.getContext().getPackageManager(), uid), phone);
+                        phone.getContext().getPackageManager(), uid), uid, phone);
     }
 
     @Override
diff --git a/src/com/android/services/telephony/RadioOnHelper.java b/src/com/android/services/telephony/RadioOnHelper.java
index 116c61d..25ac220 100644
--- a/src/com/android/services/telephony/RadioOnHelper.java
+++ b/src/com/android/services/telephony/RadioOnHelper.java
@@ -77,7 +77,8 @@
      * RadioOnHelper's handler (thus ensuring that the rest of the sequence is entirely
      * serialized, and runs on the main looper.)
      */
-    public void triggerRadioOnAndListen(RadioOnStateListener.Callback callback) {
+    public void triggerRadioOnAndListen(RadioOnStateListener.Callback callback,
+            boolean forEmergencyCall, Phone phoneForEmergencyCall) {
         setupListeners();
         mCallback = callback;
         mInProgressListeners.clear();
@@ -89,16 +90,17 @@
             }
 
             mInProgressListeners.add(mListeners.get(i));
-            mListeners.get(i).waitForRadioOn(phone, this);
+            mListeners.get(i).waitForRadioOn(phone, this, forEmergencyCall,
+                    forEmergencyCall && phone == phoneForEmergencyCall);
         }
 
-        powerOnRadio();
+        powerOnRadio(forEmergencyCall, phoneForEmergencyCall);
     }
     /**
      * Attempt to power on the radio (i.e. take the device out of airplane mode). We'll eventually
      * get an onServiceStateChanged() callback when the radio successfully comes up.
      */
-    private void powerOnRadio() {
+    private void powerOnRadio(boolean forEmergencyCall, Phone phoneForEmergencyCall) {
 
         // If airplane mode is on, we turn it off the same way that the Settings activity turns it
         // off.
@@ -112,7 +114,7 @@
 
             for (Phone phone : PhoneFactory.getPhones()) {
                 Log.d(this, "powerOnRadio, enabling Radio");
-                phone.setRadioPower(true);
+                phone.setRadioPower(true, forEmergencyCall, phone == phoneForEmergencyCall, false);
             }
 
             // Post the broadcast intend for change in airplane mode
diff --git a/src/com/android/services/telephony/RadioOnStateListener.java b/src/com/android/services/telephony/RadioOnStateListener.java
index 43269b4..1bc6969 100644
--- a/src/com/android/services/telephony/RadioOnStateListener.java
+++ b/src/com/android/services/telephony/RadioOnStateListener.java
@@ -70,7 +70,10 @@
                         Phone phone = (Phone) args.arg1;
                         RadioOnStateListener.Callback callback =
                                 (RadioOnStateListener.Callback) args.arg2;
-                        startSequenceInternal(phone, callback);
+                        boolean forEmergencyCall = (boolean) args.arg3;
+                        boolean isSelectedPhoneForEmergencyCall = (boolean) args.arg4;
+                        startSequenceInternal(phone, callback, forEmergencyCall,
+                                isSelectedPhoneForEmergencyCall);
                     } finally {
                         args.recycle();
                     }
@@ -97,6 +100,10 @@
 
     private Callback mCallback;  // The callback to notify upon completion.
     private Phone mPhone;  // The phone that will attempt to place the call.
+    private boolean mForEmergencyCall; // Whether radio is being turned on for emergency call.
+    // Whether this phone is selected to place emergency call. Can be true only if
+    // mForEmergencyCall is true.
+    private boolean mSelectedPhoneForEmergencyCall;
     private int mNumRetriesSoFar;
 
     /**
@@ -113,7 +120,8 @@
      * RadioOnStateListener's handler (thus ensuring that the rest of the sequence is entirely
      * serialized, and runs only on the handler thread.)
      */
-    public void waitForRadioOn(Phone phone, Callback callback) {
+    public void waitForRadioOn(Phone phone, Callback callback,
+            boolean forEmergencyCall, boolean isSelectedPhoneForEmergencyCall) {
         Log.d(this, "waitForRadioOn: Phone " + phone.getPhoneId());
 
         if (mPhone != null) {
@@ -124,6 +132,8 @@
         SomeArgs args = SomeArgs.obtain();
         args.arg1 = phone;
         args.arg2 = callback;
+        args.arg3 = forEmergencyCall;
+        args.arg4 = isSelectedPhoneForEmergencyCall;
         mHandler.obtainMessage(MSG_START_SEQUENCE, args).sendToTarget();
     }
 
@@ -132,7 +142,8 @@
      *
      * @see #waitForRadioOn
      */
-    private void startSequenceInternal(Phone phone, Callback callback) {
+    private void startSequenceInternal(Phone phone, Callback callback,
+            boolean forEmergencyCall, boolean isSelectedPhoneForEmergencyCall) {
         Log.d(this, "startSequenceInternal: Phone " + phone.getPhoneId());
 
         // First of all, clean up any state left over from a prior RadioOn call sequence. This
@@ -142,6 +153,8 @@
 
         mPhone = phone;
         mCallback = callback;
+        mForEmergencyCall = forEmergencyCall;
+        mSelectedPhoneForEmergencyCall = isSelectedPhoneForEmergencyCall;
 
         registerForServiceStateChanged();
         // Register for RADIO_OFF to handle cases where emergency call is dialed before
@@ -231,7 +244,8 @@
                 cleanup();
             } else {
                 Log.d(this, "Trying (again) to turn on the radio.");
-                mPhone.setRadioPower(true);
+                mPhone.setRadioPower(true, mForEmergencyCall, mSelectedPhoneForEmergencyCall,
+                        false);
                 startRetryTimer();
             }
         }
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 854d935..e133881 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -430,6 +430,14 @@
     }
 
     /**
+     * Overrides radioOnHelper for testing.
+     */
+    @VisibleForTesting
+    public void setRadioOnHelper(RadioOnHelper radioOnHelper) {
+        mRadioOnHelper = radioOnHelper;
+    }
+
+    /**
      * Overrides PhoneSwitcher dependencies for testing.
      */
     @VisibleForTesting
@@ -772,13 +780,16 @@
         boolean needToTurnOnRadio = (isEmergencyNumber && (!isRadioOn() || isAirplaneModeOn))
                 || isRadioPowerDownOnBluetooth();
 
+        // Get the right phone object from the account data passed in.
+        final Phone phone = getPhoneForAccount(request.getAccountHandle(), isEmergencyNumber,
+                /* Note: when not an emergency, handle can be null for unknown callers */
+                handle == null ? null : handle.getSchemeSpecificPart());
+
         if (needToTurnOnRadio) {
             final Uri resultHandle = handle;
-            // By default, Connection based on the default Phone, since we need to return to Telecom
-            // now.
-            final int originalPhoneType = mPhoneFactoryProxy.getDefaultPhone().getPhoneType();
+            final int originalPhoneType = phone.getPhoneType();
             final Connection resultConnection = getTelephonyConnection(request, numberToDial,
-                    isEmergencyNumber, resultHandle, PhoneFactory.getDefaultPhone());
+                    isEmergencyNumber, resultHandle, phone);
             if (mRadioOnHelper == null) {
                 mRadioOnHelper = new RadioOnHelper(this);
             }
@@ -786,7 +797,7 @@
                 @Override
                 public void onComplete(RadioOnStateListener listener, boolean isRadioReady) {
                     handleOnComplete(isRadioReady, isEmergencyNumber, resultConnection, request,
-                            numberToDial, resultHandle, originalPhoneType);
+                            numberToDial, resultHandle, originalPhoneType, phone);
                 }
 
                 @Override
@@ -815,7 +826,7 @@
                                 || serviceState == ServiceState.STATE_IN_SERVICE;
                     }
                 }
-            });
+            }, isEmergencyNumber && !isTestEmergencyNumber, phone);
             // Return the still unconnected GsmConnection and wait for the Radios to boot before
             // connecting it to the underlying Phone.
             return resultConnection;
@@ -831,10 +842,6 @@
                                 "Add call restricted due to ongoing video call"));
             }
 
-            // Get the right phone object from the account data passed in.
-            final Phone phone = getPhoneForAccount(request.getAccountHandle(), isEmergencyNumber,
-                    /* Note: when not an emergency, handle can be null for unknown callers */
-                    handle == null ? null : handle.getSchemeSpecificPart());
             if (!isEmergencyNumber) {
                 final Connection resultConnection = getTelephonyConnection(request, numberToDial,
                         false, handle, phone);
@@ -911,18 +918,21 @@
      */
     private void handleOnComplete(boolean isRadioReady, boolean isEmergencyNumber,
             Connection originalConnection, ConnectionRequest request, String numberToDial,
-            Uri handle, int originalPhoneType) {
+            Uri handle, int originalPhoneType, Phone phone) {
         // Make sure the Call has not already been canceled by the user.
         if (originalConnection.getState() == Connection.STATE_DISCONNECTED) {
             Log.i(this, "Call disconnected before the outgoing call was placed. Skipping call "
                     + "placement.");
+            if (isEmergencyNumber) {
+                // If call is already canceled by the user, notify modem to exit emergency call
+                // mode by sending radio on with forEmergencyCall=false.
+                for (Phone curPhone : mPhoneFactoryProxy.getPhones()) {
+                    curPhone.setRadioPower(true, false, false, true);
+                }
+            }
             return;
         }
-        // Get the right phone object since the radio has been turned on successfully.
         if (isRadioReady) {
-            final Phone phone = getPhoneForAccount(request.getAccountHandle(), isEmergencyNumber,
-                    /* Note: when not an emergency, handle can be null for unknown callers */
-                    handle == null ? null : handle.getSchemeSpecificPart());
             if (!isEmergencyNumber) {
                 adjustAndPlaceOutgoingConnection(phone, originalConnection, request, numberToDial,
                         handle, originalPhoneType, false);
diff --git a/src/com/android/services/telephony/rcs/UserCapabilityExchangeImpl.java b/src/com/android/services/telephony/rcs/UserCapabilityExchangeImpl.java
index d488dff..ac8f9bf 100644
--- a/src/com/android/services/telephony/rcs/UserCapabilityExchangeImpl.java
+++ b/src/com/android/services/telephony/rcs/UserCapabilityExchangeImpl.java
@@ -235,7 +235,7 @@
     private static int toUcePublishState(int publishState) {
         switch (publishState) {
             case PresenceBase.PUBLISH_STATE_200_OK:
-                return RcsUceAdapter.PUBLISH_STATE_200_OK;
+                return RcsUceAdapter.PUBLISH_STATE_OK;
             case PresenceBase.PUBLISH_STATE_NOT_PUBLISHED:
                 return RcsUceAdapter.PUBLISH_STATE_NOT_PUBLISHED;
             case PresenceBase.PUBLISH_STATE_VOLTE_PROVISION_ERROR:
diff --git a/tests/src/com/android/services/telephony/RadioOnStateListenerTest.java b/tests/src/com/android/services/telephony/RadioOnStateListenerTest.java
index afdfab5..dffbbf3 100644
--- a/tests/src/com/android/services/telephony/RadioOnStateListenerTest.java
+++ b/tests/src/com/android/services/telephony/RadioOnStateListenerTest.java
@@ -83,7 +83,7 @@
     @SmallTest
     public void testRegisterForCallback() {
         mMockPhone.mCi = mMockCi;
-        mListener.waitForRadioOn(mMockPhone, mCallback);
+        mListener.waitForRadioOn(mMockPhone, mCallback, false, false);
 
         waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
 
@@ -105,10 +105,11 @@
     public void testPhoneChangeState_OkToCallTrue() {
         ServiceState state = new ServiceState();
         state.setState(ServiceState.STATE_IN_SERVICE);
+        when(mMockPhone.getServiceState()).thenReturn(state);
         when(mMockPhone.getState()).thenReturn(PhoneConstants.State.IDLE);
         when(mCallback.isOkToCall(eq(mMockPhone), anyInt())).thenReturn(true);
         mMockPhone.mCi = mMockCi;
-        mListener.waitForRadioOn(mMockPhone, mCallback);
+        mListener.waitForRadioOn(mMockPhone, mCallback, false, false);
         waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
 
         mListener.getHandler().obtainMessage(RadioOnStateListener.MSG_SERVICE_STATE_CHANGED,
@@ -132,7 +133,7 @@
         when(mCallback.isOkToCall(eq(mMockPhone), anyInt())).thenReturn(false);
         when(mMockPhone.getServiceState()).thenReturn(state);
         mMockPhone.mCi = mMockCi;
-        mListener.waitForRadioOn(mMockPhone, mCallback);
+        mListener.waitForRadioOn(mMockPhone, mCallback, false, false);
         waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
 
         mListener.getHandler().obtainMessage(RadioOnStateListener.MSG_SERVICE_STATE_CHANGED,
@@ -161,10 +162,32 @@
 
         // Wait for the timer to expire and check state manually in onRetryTimeout
         mMockPhone.mCi = mMockCi;
-        mListener.waitForRadioOn(mMockPhone, mCallback);
+        mListener.waitForRadioOn(mMockPhone, mCallback, false, false);
         waitForHandlerActionDelayed(mListener.getHandler(), TIMEOUT_MS, TIMEOUT_MS /*delay*/);
 
         verify(mCallback).onComplete(eq(mListener), eq(false));
-        verify(mMockPhone, times(2)).setRadioPower(eq(true));
+        verify(mMockPhone, times(2)).setRadioPower(eq(true),
+                eq(false), eq(false), eq(false));
+    }
+
+    @Test
+    @SmallTest
+    public void testTimeout_RetryFailure_ForEmergency() {
+        ServiceState state = new ServiceState();
+        state.setState(ServiceState.STATE_POWER_OFF);
+        when(mMockPhone.getState()).thenReturn(PhoneConstants.State.IDLE);
+        when(mMockPhone.getServiceState()).thenReturn(state);
+        when(mCallback.isOkToCall(eq(mMockPhone), anyInt())).thenReturn(false);
+        mListener.setTimeBetweenRetriesMillis(0/*ms*/);
+        mListener.setMaxNumRetries(2);
+
+        // Wait for the timer to expire and check state manually in onRetryTimeout
+        mMockPhone.mCi = mMockCi;
+        mListener.waitForRadioOn(mMockPhone, mCallback, true, true);
+        waitForHandlerActionDelayed(mListener.getHandler(), TIMEOUT_MS, TIMEOUT_MS /*delay*/);
+
+        verify(mCallback).onComplete(eq(mListener), eq(false));
+        verify(mMockPhone, times(2)).setRadioPower(eq(true),
+                eq(true), eq(true), eq(false));
     }
 }
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index 6e11e51..2060e6f 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -16,7 +16,10 @@
 
 package com.android.services.telephony;
 
+import static com.android.internal.telephony.RILConstants.GSM_PHONE;
+
 import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.fail;
@@ -26,6 +29,7 @@
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -58,6 +62,7 @@
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneSwitcher;
+import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
 import com.android.internal.telephony.gsm.SuppServiceNotification;
 
@@ -93,6 +98,7 @@
     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");
+    private android.telecom.Connection mConnection;
 
     @Mock TelephonyConnectionService.TelephonyManagerProxy mTelephonyManagerProxy;
     @Mock TelephonyConnectionService.SubscriptionManagerProxy mSubscriptionManagerProxy;
@@ -106,6 +112,8 @@
     @Mock Handler mMockHandler;
     @Mock EmergencyNumberTracker mEmergencyNumberTracker;
     @Mock PhoneSwitcher mPhoneSwitcher;
+    @Mock RadioOnHelper mRadioOnHelper;
+    @Mock ServiceStateTracker mSST;
 
     private static class TestTelephonyConnectionService extends TelephonyConnectionService {
 
@@ -135,6 +143,8 @@
         doReturn(false).when(mDeviceState).shouldCheckSimStateBeforeOutgoingCall(any());
         mTestConnectionService.setPhoneSwitcherProxy(mPhoneSwitcherProxy);
         doReturn(mPhoneSwitcher).when(mPhoneSwitcherProxy).getPhoneSwitcher();
+        when(mPhoneNumberUtilsProxy.convertToEmergencyNumber(any(), anyString()))
+                .thenAnswer(invocation -> invocation.getArgument(1));
         mTestConnectionService.setPhoneNumberUtilsProxy(mPhoneNumberUtilsProxy);
         mTestConnectionService.setPhoneUtilsProxy(mPhoneUtilsProxy);
         HandlerThread mockHandlerThread = mock(HandlerThread.class);
@@ -143,6 +153,7 @@
         doReturn(mMockHandler).when(mHandlerFactory).createHandler(any());
         mTestConnectionService.setHandlerFactory(mHandlerFactory);
         mTestConnectionService.setDeviceState(mDeviceState);
+        mTestConnectionService.setRadioOnHelper(mRadioOnHelper);
         doReturn(new DisconnectCause(DisconnectCause.UNKNOWN)).when(mDisconnectCauseFactory)
                 .toTelecomDisconnectCause(anyInt(), any());
         doReturn(new DisconnectCause(DisconnectCause.UNKNOWN)).when(mDisconnectCauseFactory)
@@ -941,6 +952,64 @@
     }
 
     /**
+     * Test that the TelephonyConnectionService successfully turns radio on before placing the
+     * emergency call.
+     */
+    @Test
+    @SmallTest
+    public void testCreateOutgoingEmerge_exitingApm_disconnected() {
+        when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
+        Phone testPhone = setupConnectionServiceInApm();
+
+        ArgumentCaptor<RadioOnStateListener.Callback> callback =
+                ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
+        verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
+                eq(testPhone));
+
+        assertFalse(callback.getValue().isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE));
+        when(mSST.isRadioOn()).thenReturn(true);
+        assertTrue(callback.getValue().isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE));
+
+        mConnection.setDisconnected(null);
+        callback.getValue().onComplete(null, true);
+        for (Phone phone : mPhoneFactoryProxy.getPhones()) {
+            verify(phone).setRadioPower(true, false, false, true);
+        }
+    }
+
+    /**
+     * Test that the TelephonyConnectionService successfully turns radio on before placing the
+     * emergency call.
+     */
+    @Test
+    @SmallTest
+    public void testCreateOutgoingEmergencyConnection_exitingApm_placeCall() {
+        when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
+        Phone testPhone = setupConnectionServiceInApm();
+
+        ArgumentCaptor<RadioOnStateListener.Callback> callback =
+                ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
+        verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
+                eq(testPhone));
+
+        assertFalse(callback.getValue().isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE));
+        when(mSST.isRadioOn()).thenReturn(true);
+        assertTrue(callback.getValue().isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE));
+
+        callback.getValue().onComplete(null, true);
+        Runnable delayDialRunnable = verifyRunnablePosted();
+
+        try {
+            doAnswer(invocation -> null).when(mContext).startActivity(any());
+            delayDialRunnable.run();
+            verify(testPhone).dial(anyString(), any());
+        } catch (CallStateException e) {
+            // This shouldn't happen
+            fail();
+        }
+    }
+
+    /**
      * Test that the TelephonyConnectionService does not perform a DDS switch when the carrier
      * supports control-plane fallback.
      */
@@ -1115,9 +1184,49 @@
         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);
+        mConnection = mTestConnectionService.onCreateOutgoingConnection(
+                PHONE_ACCOUNT_HANDLE_1, connectionRequest);
+        assertNotNull("test connection was not set up correctly.", mConnection);
+
+        return testPhone0;
+    }
+
+
+    /**
+     * Set up a mock MSIM device with TEST_ADDRESS set as an emergency number in airplane mode.
+     * @return the Phone associated with slot 0.
+     */
+    private Phone setupConnectionServiceInApm() {
+        ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
+                .setAccountHandle(PHONE_ACCOUNT_HANDLE_1)
+                .setAddress(TEST_ADDRESS)
+                .build();
+        Phone testPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_POWER_OFF,
+                false /*isEmergencyOnly*/);
+        Phone testPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_POWER_OFF,
+                false /*isEmergencyOnly*/);
+        doReturn(GSM_PHONE).when(testPhone0).getPhoneType();
+        doReturn(GSM_PHONE).when(testPhone1).getPhoneType();
+        List<Phone> phones = new ArrayList<>(2);
+        doReturn(false).when(testPhone0).isRadioOn();
+        doReturn(false).when(testPhone1).isRadioOn();
+        phones.add(testPhone0);
+        phones.add(testPhone1);
+        setPhones(phones);
+        setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_1, testPhone0);
+        setupDeviceConfig(testPhone0, testPhone1, 0);
+        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();
+
+        mConnection = mTestConnectionService.onCreateOutgoingConnection(
+                PHONE_ACCOUNT_HANDLE_1, connectionRequest);
+        assertNotNull("test connection was not set up correctly.", mConnection);
 
         return testPhone0;
     }
@@ -1163,6 +1272,7 @@
         when(phone.getPhoneId()).thenReturn(phoneId);
         when(phone.getDefaultPhone()).thenReturn(phone);
         when(phone.getEmergencyNumberTracker()).thenReturn(mEmergencyNumberTracker);
+        when(phone.getServiceStateTracker()).thenReturn(mSST);
         when(mEmergencyNumberTracker.getEmergencyNumber(anyString())).thenReturn(null);
         return phone;
     }
@@ -1193,6 +1303,7 @@
 
     private void setPhones(List<Phone> phones) {
         when(mPhoneFactoryProxy.getPhones()).thenReturn(phones.toArray(new Phone[phones.size()]));
+        when(mPhoneFactoryProxy.getDefaultPhone()).thenReturn(phones.get(0));
     }
 
     private void setPhonesDialConnection(Phone phone, Connection c) {