1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.services.telephony;
18 
19 import static android.telecom.Connection.PROPERTY_WIFI;
20 import static android.telephony.DisconnectCause.EMERGENCY_PERM_FAILURE;
21 import static android.telephony.DisconnectCause.EMERGENCY_TEMP_FAILURE;
22 import static android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
23 import static android.telephony.DisconnectCause.NOT_DISCONNECTED;
24 import static android.telephony.DomainSelectionService.SELECTOR_TYPE_CALLING;
25 import static android.telephony.NetworkRegistrationInfo.DOMAIN_CS;
26 import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
27 import static android.telephony.emergency.EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE;
28 import static android.telephony.ims.ImsReasonInfo.CODE_SIP_ALTERNATE_EMERGENCY_CALL;
29 
30 import static com.android.internal.telephony.RILConstants.GSM_PHONE;
31 import static com.android.services.telephony.TelephonyConnectionService.TIMEOUT_TO_DYNAMIC_ROUTING_MS;
32 
33 import static junit.framework.Assert.assertEquals;
34 import static junit.framework.Assert.assertFalse;
35 import static junit.framework.Assert.assertNotNull;
36 import static junit.framework.Assert.assertNull;
37 import static junit.framework.Assert.assertTrue;
38 import static junit.framework.Assert.fail;
39 
40 import static org.junit.Assert.assertThrows;
41 import static org.mockito.ArgumentMatchers.any;
42 import static org.mockito.ArgumentMatchers.anyBoolean;
43 import static org.mockito.ArgumentMatchers.anyInt;
44 import static org.mockito.ArgumentMatchers.anyString;
45 import static org.mockito.Matchers.eq;
46 import static org.mockito.Mockito.doAnswer;
47 import static org.mockito.Mockito.doNothing;
48 import static org.mockito.Mockito.doReturn;
49 import static org.mockito.Mockito.doThrow;
50 import static org.mockito.Mockito.mock;
51 import static org.mockito.Mockito.never;
52 import static org.mockito.Mockito.times;
53 import static org.mockito.Mockito.verify;
54 import static org.mockito.Mockito.verifyZeroInteractions;
55 import static org.mockito.Mockito.when;
56 
57 import android.content.ComponentName;
58 import android.content.Context;
59 import android.content.res.Resources;
60 import android.net.Uri;
61 import android.os.AsyncResult;
62 import android.os.Bundle;
63 import android.os.Handler;
64 import android.platform.test.flag.junit.SetFlagsRule;
65 import android.telecom.Conference;
66 import android.telecom.Conferenceable;
67 import android.telecom.ConnectionRequest;
68 import android.telecom.DisconnectCause;
69 import android.telecom.PhoneAccount;
70 import android.telecom.PhoneAccountHandle;
71 import android.telecom.TelecomManager;
72 import android.telephony.AccessNetworkConstants;
73 import android.telephony.CarrierConfigManager;
74 import android.telephony.DataSpecificRegistrationInfo;
75 import android.telephony.DomainSelectionService;
76 import android.telephony.NetworkRegistrationInfo;
77 import android.telephony.RadioAccessFamily;
78 import android.telephony.ServiceState;
79 import android.telephony.SubscriptionManager;
80 import android.telephony.TelephonyManager;
81 import android.telephony.emergency.EmergencyNumber;
82 import android.telephony.ims.ImsReasonInfo;
83 import android.telephony.ims.stub.ImsRegistrationImplBase;
84 import android.util.ArrayMap;
85 
86 import androidx.test.filters.SmallTest;
87 import androidx.test.runner.AndroidJUnit4;
88 
89 import com.android.TelephonyTestBase;
90 import com.android.ims.ImsManager;
91 import com.android.internal.telecom.IConnectionService;
92 import com.android.internal.telephony.Call;
93 import com.android.internal.telephony.CallStateException;
94 import com.android.internal.telephony.Connection;
95 import com.android.internal.telephony.Phone;
96 import com.android.internal.telephony.PhoneConstants;
97 import com.android.internal.telephony.PhoneInternalInterface.DialArgs;
98 import com.android.internal.telephony.ServiceStateTracker;
99 import com.android.internal.telephony.data.PhoneSwitcher;
100 import com.android.internal.telephony.domainselection.DomainSelectionConnection;
101 import com.android.internal.telephony.domainselection.DomainSelectionResolver;
102 import com.android.internal.telephony.domainselection.EmergencyCallDomainSelectionConnection;
103 import com.android.internal.telephony.domainselection.NormalCallDomainSelectionConnection;
104 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
105 import com.android.internal.telephony.emergency.EmergencyStateTracker;
106 import com.android.internal.telephony.emergency.RadioOnHelper;
107 import com.android.internal.telephony.emergency.RadioOnStateListener;
108 import com.android.internal.telephony.flags.FeatureFlags;
109 import com.android.internal.telephony.flags.Flags;
110 import com.android.internal.telephony.gsm.SuppServiceNotification;
111 import com.android.internal.telephony.imsphone.ImsPhone;
112 import com.android.internal.telephony.satellite.SatelliteController;
113 import com.android.internal.telephony.satellite.SatelliteSOSMessageRecommender;
114 import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
115 import com.android.internal.telephony.subscription.SubscriptionManagerService;
116 
117 import org.junit.After;
118 import org.junit.Before;
119 import org.junit.Rule;
120 import org.junit.Test;
121 import org.junit.runner.RunWith;
122 import org.mockito.ArgumentCaptor;
123 import org.mockito.Mock;
124 import org.mockito.Mockito;
125 
126 import java.util.ArrayList;
127 import java.util.Arrays;
128 import java.util.Collection;
129 import java.util.Collections;
130 import java.util.HashMap;
131 import java.util.List;
132 import java.util.Map;
133 import java.util.concurrent.CompletableFuture;
134 import java.util.concurrent.Executor;
135 import java.util.function.Consumer;
136 
137 /**
138  * Unit tests for TelephonyConnectionService.
139  */
140 
141 @RunWith(AndroidJUnit4.class)
142 public class TelephonyConnectionServiceTest extends TelephonyTestBase {
143     @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
144     private static final String NORMAL_ROUTED_EMERGENCY_NUMBER = "110";
145     private static final String EMERGENCY_ROUTED_EMERGENCY_NUMBER = "911";
146     private static final EmergencyNumber MOCK_NORMAL_NUMBER = new EmergencyNumber(
147             NORMAL_ROUTED_EMERGENCY_NUMBER,
148             "US" /* country */,
149             null /* mcc */,
150             EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
151             Collections.emptyList() /* categories */,
152             EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
153             EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
154     private static final EmergencyNumber MOCK_NORMAL_NUMBER_WITH_UNKNOWN_ROUTING =
155             new EmergencyNumber(
156                     NORMAL_ROUTED_EMERGENCY_NUMBER,
157                     "US" /* country */,
158                     "455" /* mcc */,
159                     EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
160                     Collections.emptyList() /* categories */,
161                     EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
162                     EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN);
163     private static final EmergencyNumber MOCK_EMERGENCY_NUMBER = new EmergencyNumber(
164             EMERGENCY_ROUTED_EMERGENCY_NUMBER,
165             "US" /* country */,
166             null /* mcc */,
167             EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
168             Collections.emptyList() /* categories */,
169             EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
170             EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY);
171 
172     /**
173      * Unlike {@link TestTelephonyConnection}, a bare minimal {@link TelephonyConnection} impl
174      * that does not try to configure anything.
175      */
176     public static class SimpleTelephonyConnection extends TelephonyConnection {
177         public boolean wasDisconnected = false;
178         public boolean wasUnheld = false;
179         public boolean wasHeld = false;
180 
181         @Override
cloneConnection()182         public TelephonyConnection cloneConnection() {
183             return null;
184         }
185 
186         @Override
hangup(int telephonyDisconnectCode)187         public void hangup(int telephonyDisconnectCode) {
188             wasDisconnected = true;
189         }
190 
191         @Override
onUnhold()192         public void onUnhold() {
193             wasUnheld = true;
194         }
195 
196         @Override
onHold()197         public void onHold() {
198             wasHeld = true;
199         }
200     }
201 
202     public static class SimpleConference extends Conference {
203         public boolean wasUnheld = false;
204 
SimpleConference(PhoneAccountHandle phoneAccountHandle)205         public SimpleConference(PhoneAccountHandle phoneAccountHandle) {
206             super(phoneAccountHandle);
207         }
208 
209         @Override
onUnhold()210         public void onUnhold() {
211             wasUnheld = true;
212         }
213     }
214 
215     private static final long TIMEOUT_MS = 100;
216     private static final int SLOT_0_PHONE_ID = 0;
217     private static final int SLOT_1_PHONE_ID = 1;
218 
219     private static final ComponentName TEST_COMPONENT_NAME = new ComponentName(
220             "com.android.phone.tests", TelephonyConnectionServiceTest.class.getName());
221     private static final String TEST_ACCOUNT_ID1 = "0"; // subid 0
222     private static final String TEST_ACCOUNT_ID2 = "1"; // subid 1
223     private static final PhoneAccountHandle PHONE_ACCOUNT_HANDLE_1 = new PhoneAccountHandle(
224             TEST_COMPONENT_NAME, TEST_ACCOUNT_ID1);
225     private static final PhoneAccountHandle PHONE_ACCOUNT_HANDLE_2 = new PhoneAccountHandle(
226             TEST_COMPONENT_NAME, TEST_ACCOUNT_ID2);
227     private static final Uri TEST_ADDRESS = Uri.parse("tel:+16505551212");
228     private static final String TELECOM_CALL_ID1 = "TC1";
229     private static final String TEST_EMERGENCY_NUMBER = "911";
230     private static final String DISCONNECT_REASON_SATELLITE_ENABLED = "SATELLITE_ENABLED";
231     private static final String DISCONNECT_REASON_CARRIER_ROAMING_SATELLITE_MODE =
232             "CARRIER_ROAMING_SATELLITE_MODE";
233     private android.telecom.Connection mConnection;
234 
235     @Mock TelephonyConnectionService.TelephonyManagerProxy mTelephonyManagerProxy;
236     @Mock TelephonyConnectionService.SubscriptionManagerProxy mSubscriptionManagerProxy;
237     @Mock TelephonyConnectionService.PhoneFactoryProxy mPhoneFactoryProxy;
238     @Mock DeviceState mDeviceState;
239     @Mock TelephonyConnectionService.PhoneSwitcherProxy mPhoneSwitcherProxy;
240     @Mock TelephonyConnectionService.PhoneNumberUtilsProxy mPhoneNumberUtilsProxy;
241     @Mock TelephonyConnectionService.PhoneUtilsProxy mPhoneUtilsProxy;
242     @Mock TelephonyConnectionService.DisconnectCauseFactory mDisconnectCauseFactory;
243     @Mock SatelliteController mSatelliteController;
244     @Mock EmergencyNumberTracker mEmergencyNumberTracker;
245     @Mock PhoneSwitcher mPhoneSwitcher;
246     @Mock RadioOnHelper mRadioOnHelper;
247     @Mock ServiceStateTracker mSST;
248     @Mock Call mCall;
249     @Mock Call mCall2;
250     @Mock com.android.internal.telephony.Connection mInternalConnection;
251     @Mock com.android.internal.telephony.Connection mInternalConnection2;
252     @Mock DomainSelectionResolver mDomainSelectionResolver;
253     @Mock EmergencyCallDomainSelectionConnection mEmergencyCallDomainSelectionConnection;
254     @Mock NormalCallDomainSelectionConnection mNormalCallDomainSelectionConnection;
255     @Mock ImsPhone mImsPhone;
256     @Mock private SatelliteSOSMessageRecommender mSatelliteSOSMessageRecommender;
257     @Mock private EmergencyStateTracker mEmergencyStateTracker;
258     @Mock private Resources mMockResources;
259     @Mock private FeatureFlags mFeatureFlags;
260     private Phone mPhone0;
261     private Phone mPhone1;
262 
263     private static class TestTelephonyConnectionService extends TelephonyConnectionService {
264 
265         private final Context mContext;
266 
TestTelephonyConnectionService(Context context)267         TestTelephonyConnectionService(Context context) {
268             mContext = context;
269         }
270 
271         @Override
onCreate()272         public void onCreate() {
273             // attach test context.
274             attachBaseContext(mContext);
275             super.onCreate();
276         }
277     }
278 
279     private TelephonyConnectionService mTestConnectionService;
280     private IConnectionService.Stub mBinderStub;
281 
282     @Before
setUp()283     public void setUp() throws Exception {
284         super.setUp();
285 
286         mTestConnectionService = new TestTelephonyConnectionService(mContext);
287         mTestConnectionService.setFeatureFlags(mFeatureFlags);
288         mTestConnectionService.setPhoneFactoryProxy(mPhoneFactoryProxy);
289         mTestConnectionService.setSubscriptionManagerProxy(mSubscriptionManagerProxy);
290         // Set configurations statically
291         doReturn(false).when(mDeviceState).shouldCheckSimStateBeforeOutgoingCall(any());
292         mTestConnectionService.setPhoneSwitcherProxy(mPhoneSwitcherProxy);
293         doReturn(mPhoneSwitcher).when(mPhoneSwitcherProxy).getPhoneSwitcher();
294         when(mPhoneNumberUtilsProxy.convertToEmergencyNumber(any(), anyString()))
295                 .thenAnswer(invocation -> invocation.getArgument(1));
296         mTestConnectionService.setPhoneNumberUtilsProxy(mPhoneNumberUtilsProxy);
297         mTestConnectionService.setPhoneUtilsProxy(mPhoneUtilsProxy);
298         mTestConnectionService.setDeviceState(mDeviceState);
299         mTestConnectionService.setRadioOnHelper(mRadioOnHelper);
300         doAnswer(invocation -> DisconnectCauseUtil.toTelecomDisconnectCause(
301                 invocation.getArgument(0), invocation.getArgument(1)))
302                 .when(mDisconnectCauseFactory).toTelecomDisconnectCause(anyInt(), any());
303         doAnswer(invocation -> DisconnectCauseUtil.toTelecomDisconnectCause(
304                 invocation.getArgument(0), invocation.getArgument(1),
305                 (int) invocation.getArgument(2)))
306                 .when(mDisconnectCauseFactory).toTelecomDisconnectCause(anyInt(), any(), anyInt());
307         mTestConnectionService.setDisconnectCauseFactory(mDisconnectCauseFactory);
308         mTestConnectionService.onCreate();
309         mTestConnectionService.setTelephonyManagerProxy(mTelephonyManagerProxy);
310         replaceInstance(TelephonyConnectionService.class, "mDomainSelectionResolver",
311                 mTestConnectionService, mDomainSelectionResolver);
312         replaceInstance(TelephonyConnectionService.class, "mEmergencyStateTracker",
313                 mTestConnectionService, mEmergencyStateTracker);
314         replaceInstance(TelephonyConnectionService.class, "mSatelliteSOSMessageRecommender",
315                 mTestConnectionService, mSatelliteSOSMessageRecommender);
316         doNothing().when(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(),
317                 anyBoolean());
318         doNothing().when(mSatelliteSOSMessageRecommender).onEmergencyCallConnectionStateChanged(
319                 anyString(), anyInt());
320         doReturn(CompletableFuture.completedFuture(NOT_DISCONNECTED))
321                 .when(mEmergencyStateTracker)
322                 .startEmergencyCall(any(), any(), eq(false));
323         replaceInstance(TelephonyConnectionService.class,
324                 "mDomainSelectionMainExecutor", mTestConnectionService, getExecutor());
325         doReturn(false).when(mDomainSelectionResolver).isDomainSelectionSupported();
326         doReturn(null).when(mDomainSelectionResolver).getDomainSelectionConnection(
327                 any(), anyInt(), anyBoolean());
328         replaceInstance(TelephonyConnectionService.class,
329                 "mSatelliteController", mTestConnectionService, mSatelliteController);
330         doReturn(mMockResources).when(mContext).getResources();
331 
332         mBinderStub = (IConnectionService.Stub) mTestConnectionService.onBind(null);
333         mSetFlagsRule.disableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
334         mSetFlagsRule.enableFlags(Flags.FLAG_DO_NOT_OVERRIDE_PRECISE_LABEL);
335         mSetFlagsRule.enableFlags(Flags.FLAG_CALL_EXTRA_FOR_NON_HOLD_SUPPORTED_CARRIERS);
336     }
337 
338     @After
tearDown()339     public void tearDown() throws Exception {
340         if (mTestConnectionService != null
341                 && mTestConnectionService.getEmergencyConnection() != null) {
342             mTestConnectionService.onLocalHangup(mTestConnectionService.getEmergencyConnection());
343         }
344         mTestConnectionService = null;
345         super.tearDown();
346     }
347 
348     /**
349      * Prerequisites:
350      * - MSIM Device, two slots with SIMs inserted
351      * - Slot 0 is IN_SERVICE, Slot 1 is OUT_OF_SERVICE (emergency calls only)
352      * - Slot 1 is in Emergency SMS Mode
353      *
354      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone
355      */
356     @Test
357     @SmallTest
testEmergencySmsModeSimEmergencyOnly()358     public void testEmergencySmsModeSimEmergencyOnly() {
359         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_IN_SERVICE,
360                 false /*isEmergencyOnly*/);
361         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
362                 true /*isEmergencyOnly*/);
363         setDefaultPhone(slot0Phone);
364         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
365         setEmergencySmsMode(slot1Phone, true);
366 
367         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
368 
369         assertEquals(slot1Phone, resultPhone);
370     }
371 
372     /**
373      * Prerequisites:
374      * - MSIM Device, two slots with SIMs inserted
375      * - Slot 0 is IN_SERVICE, Slot 1 is OUT_OF_SERVICE
376      * - Slot 1 is in Emergency SMS Mode
377      *
378      * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone
379      */
380     @Test
381     @SmallTest
testEmergencySmsModeSimOutOfService()382     public void testEmergencySmsModeSimOutOfService() {
383         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_IN_SERVICE,
384                 false /*isEmergencyOnly*/);
385         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
386                 false /*isEmergencyOnly*/);
387         setDefaultPhone(slot0Phone);
388         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
389         setEmergencySmsMode(slot1Phone, true);
390 
391         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
392 
393         assertEquals(slot0Phone, resultPhone);
394     }
395 
396     /**
397      * Prerequisites:
398      * - MSIM Device, two slots with SIMs inserted
399      * - Users default Voice SIM choice is IN_SERVICE
400      *
401      * Result: getFirstPhoneForEmergencyCall returns the default Voice SIM choice.
402      */
403     @Test
404     @SmallTest
testDefaultVoiceSimInService()405     public void testDefaultVoiceSimInService() {
406         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_IN_SERVICE,
407                 false /*isEmergencyOnly*/);
408         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
409                 true /*isEmergencyOnly*/);
410         setDefaultPhone(slot0Phone);
411         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
412 
413         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
414 
415         assertEquals(slot0Phone, resultPhone);
416     }
417 
418     /**
419      * Prerequisites:
420      * - MSIM Device, two slots with SIMs inserted
421      * - Users default data SIM choice is OUT_OF_SERVICE (emergency calls only)
422      *
423      * Result: getFirstPhoneForEmergencyCall returns the default data SIM choice.
424      */
425     @Test
426     @SmallTest
testDefaultDataSimEmergencyOnly()427     public void testDefaultDataSimEmergencyOnly() {
428         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_IN_SERVICE,
429                 false /*isEmergencyOnly*/);
430         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
431                 true /*isEmergencyOnly*/);
432         setDefaultPhone(slot0Phone);
433         setupDeviceConfig(slot0Phone, slot1Phone, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
434         setDefaultDataPhoneId(SLOT_1_PHONE_ID);
435 
436         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
437 
438         assertEquals(slot1Phone, resultPhone);
439     }
440 
441     /**
442      * Prerequisites:
443      * - MSIM Device, two slots with SIMs inserted
444      * - Users default data SIM choice is OUT_OF_SERVICE
445      *
446      * Result: getFirstPhoneForEmergencyCall does not return the default data SIM choice.
447      */
448     @Test
449     @SmallTest
testDefaultDataSimOutOfService()450     public void testDefaultDataSimOutOfService() {
451         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_IN_SERVICE,
452                 false /*isEmergencyOnly*/);
453         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
454                 false /*isEmergencyOnly*/);
455         setDefaultPhone(slot0Phone);
456         setupDeviceConfig(slot0Phone, slot1Phone, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
457         setDefaultDataPhoneId(SLOT_1_PHONE_ID);
458 
459         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
460 
461         assertEquals(slot0Phone, resultPhone);
462     }
463 
464     /**
465      * Prerequisites:
466      * - MSIM Device, two slots with SIMs inserted
467      * - Slot 0 is OUT_OF_SERVICE, Slot 1 is OUT_OF_SERVICE (emergency calls only)
468      *
469      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone
470      */
471     @Test
472     @SmallTest
testSlot1EmergencyOnly()473     public void testSlot1EmergencyOnly() {
474         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
475                 false /*isEmergencyOnly*/);
476         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
477                 true /*isEmergencyOnly*/);
478         setDefaultPhone(slot0Phone);
479         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
480 
481         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
482 
483         assertEquals(slot1Phone, resultPhone);
484     }
485 
486     /**
487      * Prerequisites:
488      * - MSIM Device, two slots with SIMs inserted
489      * - Slot 0 is OUT_OF_SERVICE, Slot 1 is IN_SERVICE
490      *
491      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone
492      */
493     @Test
494     @SmallTest
testSlot1InService()495     public void testSlot1InService() {
496         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
497                 false /*isEmergencyOnly*/);
498         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_IN_SERVICE,
499                 false /*isEmergencyOnly*/);
500         setDefaultPhone(slot0Phone);
501         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
502 
503         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
504 
505         assertEquals(slot1Phone, resultPhone);
506     }
507 
508     /**
509      * Prerequisites:
510      * - MSIM Device, two slots with SIMs inserted
511      * - Slot 0 is PUK locked, Slot 1 is ready
512      * - Slot 0 is LTE capable, Slot 1 is GSM capable
513      *
514      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone. Although Slot 0 is more
515      * capable, it is locked, so use the other slot.
516      */
517     @Test
518     @SmallTest
testSlot0PukLocked()519     public void testSlot0PukLocked() {
520         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
521                 false /*isEmergencyOnly*/);
522         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
523                 false /*isEmergencyOnly*/);
524         setDefaultPhone(slot0Phone);
525         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
526         // Set Slot 0 to be PUK locked
527         setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_PUK_REQUIRED);
528         setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
529         // Make Slot 0 higher capability
530         setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
531         setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_GSM);
532 
533         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
534 
535         assertEquals(slot1Phone, resultPhone);
536     }
537 
538     /**
539      * Prerequisites:
540      * - MSIM Device, two slots with SIMs inserted
541      * - Slot 0 is PIN locked, Slot 1 is ready
542      * - Slot 0 is LTE capable, Slot 1 is GSM capable
543      *
544      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone. Although Slot 0 is more
545      * capable, it is locked, so use the other slot.
546      */
547     @Test
548     @SmallTest
testSlot0PinLocked()549     public void testSlot0PinLocked() {
550         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
551                 false /*isEmergencyOnly*/);
552         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
553                 false /*isEmergencyOnly*/);
554         setDefaultPhone(slot0Phone);
555         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
556         // Set Slot 0 to be PUK locked
557         setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_PIN_REQUIRED);
558         setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
559         // Make Slot 0 higher capability
560         setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
561         setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_GSM);
562 
563         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
564 
565         assertEquals(slot1Phone, resultPhone);
566     }
567 
568     /**
569      * Prerequisites:
570      * - MSIM Device, two slots with SIMs inserted
571      * - Slot 1 is PUK locked, Slot 0 is ready
572      * - Slot 1 is LTE capable, Slot 0 is GSM capable
573      *
574      * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone. Although Slot 1 is more
575      * capable, it is locked, so use the other slot.
576      */
577     @Test
578     @SmallTest
testSlot1PukLocked()579     public void testSlot1PukLocked() {
580         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
581                 false /*isEmergencyOnly*/);
582         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
583                 false /*isEmergencyOnly*/);
584         setDefaultPhone(slot0Phone);
585         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
586         // Set Slot 1 to be PUK locked
587         setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY);
588         setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_PUK_REQUIRED);
589         // Make Slot 1 higher capability
590         setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM);
591         setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
592 
593         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
594 
595         assertEquals(slot0Phone, resultPhone);
596     }
597 
598     /**
599      * Prerequisites:
600      * - MSIM Device, two slots with SIMs inserted
601      * - Slot 1 is PIN locked, Slot 0 is ready
602      * - Slot 1 is LTE capable, Slot 0 is GSM capable
603      *
604      * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone. Although Slot 1 is more
605      * capable, it is locked, so use the other slot.
606      */
607     @Test
608     @SmallTest
testSlot1PinLocked()609     public void testSlot1PinLocked() {
610         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
611                 false /*isEmergencyOnly*/);
612         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
613                 false /*isEmergencyOnly*/);
614         setDefaultPhone(slot0Phone);
615         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
616         // Set Slot 1 to be PUK locked
617         setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY);
618         setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_PIN_REQUIRED);
619         // Make Slot 1 higher capability
620         setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM);
621         setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
622 
623         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
624 
625         assertEquals(slot0Phone, resultPhone);
626     }
627 
628     /**
629      * Prerequisites:
630      * - MSIM Device, only slot 1 inserted and PUK locked
631      * - slot 1 has higher capabilities
632      *
633      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it is the only one
634      * with a SIM inserted (even if it is PUK locked)
635      */
636     @Test
637     @SmallTest
testSlot1PinLockedAndSlot0Absent()638     public void testSlot1PinLockedAndSlot0Absent() {
639         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
640                 false /*isEmergencyOnly*/);
641         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
642                 false /*isEmergencyOnly*/);
643         setDefaultPhone(slot0Phone);
644         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
645         setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT);
646         setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_PIN_REQUIRED);
647         // Slot 1 has more capabilities
648         setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM);
649         setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
650 
651         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
652 
653         assertEquals(slot1Phone, resultPhone);
654     }
655 
656     /**
657      * Prerequisites:
658      * - MSIM Device, two slots with SIMs inserted
659      * - Slot 1 is LTE capable, Slot 0 is GSM capable
660      *
661      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it is more capable
662      */
663     @Test
664     @SmallTest
testSlot1HigherCapability()665     public void testSlot1HigherCapability() {
666         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
667                 false /*isEmergencyOnly*/);
668         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
669                 false /*isEmergencyOnly*/);
670         setDefaultPhone(slot0Phone);
671         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
672         setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY);
673         setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
674         // Make Slot 1 higher capability
675         setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM);
676         setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
677 
678         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
679 
680         assertEquals(slot1Phone, resultPhone);
681     }
682 
683     /**
684      * Prerequisites:
685      * - MSIM Device, two slots with SIMs inserted
686      * - Slot 1 is GSM/LTE capable, Slot 0 is GSM capable
687      *
688      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it has more
689      * capabilities.
690      */
691     @Test
692     @SmallTest
testSlot1MoreCapabilities()693     public void testSlot1MoreCapabilities() {
694         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
695                 false /*isEmergencyOnly*/);
696         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
697                 false /*isEmergencyOnly*/);
698         setDefaultPhone(slot0Phone);
699         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
700         setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY);
701         setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
702         // Make Slot 1 more capable
703         setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
704         setPhoneRadioAccessFamily(slot1Phone,
705                 RadioAccessFamily.RAF_GSM | RadioAccessFamily.RAF_LTE);
706 
707         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
708 
709         assertEquals(slot1Phone, resultPhone);
710     }
711 
712     /**
713      * Prerequisites:
714      * - MSIM Device, two slots with SIMs inserted
715      * - Both SIMs PUK Locked
716      * - Slot 0 is LTE capable, Slot 1 is GSM capable
717      *
718      * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone because it is more capable,
719      * ignoring that both SIMs are PUK locked.
720      */
721     @Test
722     @SmallTest
testSlot0MoreCapableBothPukLocked()723     public void testSlot0MoreCapableBothPukLocked() {
724         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
725                 false /*isEmergencyOnly*/);
726         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
727                 false /*isEmergencyOnly*/);
728         setDefaultPhone(slot0Phone);
729         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
730         setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_PUK_REQUIRED);
731         setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_PUK_REQUIRED);
732         // Make Slot 0 higher capability
733         setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
734         setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_GSM);
735 
736         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
737 
738         assertEquals(slot0Phone, resultPhone);
739     }
740 
741     /**
742      * Prerequisites:
743      * - MSIM Device, two slots with SIMs inserted
744      * - Both SIMs have the same capability
745      *
746      * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone because it is the first slot.
747      */
748     @Test
749     @SmallTest
testEqualCapabilityTwoSimsInserted()750     public void testEqualCapabilityTwoSimsInserted() {
751         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
752                 false /*isEmergencyOnly*/);
753         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
754                 false /*isEmergencyOnly*/);
755         setDefaultPhone(slot0Phone);
756         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
757         setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY);
758         setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
759         // Make Capability the same
760         setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
761         setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
762 
763         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
764 
765         assertEquals(slot0Phone, resultPhone);
766     }
767 
768     /**
769      * Prerequisites:
770      * - MSIM Device, only slot 0 inserted
771      * - Both SIMs have the same capability
772      *
773      * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone because it is the only one
774      * with a SIM inserted
775      */
776     @Test
777     @SmallTest
testEqualCapabilitySim0Inserted()778     public void testEqualCapabilitySim0Inserted() {
779         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
780                 false /*isEmergencyOnly*/);
781         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
782                 false /*isEmergencyOnly*/);
783         setDefaultPhone(slot0Phone);
784         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
785         setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY);
786         setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT);
787         // Make Capability the same
788         setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
789         setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
790 
791         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
792 
793         assertEquals(slot0Phone, resultPhone);
794     }
795 
796     /**
797      * Prerequisites:
798      * - MSIM Device, only slot 1 inserted
799      * - Both SIMs have the same capability
800      *
801      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it is the only one
802      * with a SIM inserted
803      */
804     @Test
805     @SmallTest
testEqualCapabilitySim1Inserted()806     public void testEqualCapabilitySim1Inserted() {
807         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
808                 false /*isEmergencyOnly*/);
809         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
810                 false /*isEmergencyOnly*/);
811         setDefaultPhone(slot0Phone);
812         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
813         setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT);
814         setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
815         // Make Capability the same
816         setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
817         setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
818 
819         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
820 
821         assertEquals(slot1Phone, resultPhone);
822     }
823 
824     /**
825      * Prerequisites:
826      * - MSIM Device with one ESIM, only slot 1 inserted has PSIM inserted
827      * - Both phones have the same capability
828      *
829      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it is the only one
830      * with a SIM inserted
831      */
832     @Test
833     @SmallTest
testEqualCapabilitySim1Inserted_WithOneEsim()834     public void testEqualCapabilitySim1Inserted_WithOneEsim() {
835         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
836             false /*isEmergencyOnly*/);
837         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
838             false /*isEmergencyOnly*/);
839         setDefaultPhone(slot0Phone);
840         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
841         when(slot0Phone.getSubId()).thenReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
842         setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY);
843         setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
844         // Make Capability the same
845         setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
846         setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
847 
848         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
849 
850         assertEquals(slot1Phone, resultPhone);
851     }
852 
853     /**
854      * Prerequisites:
855      * - MSIM Device, no SIMs inserted
856      * - SIM 1 has the higher capability
857      *
858      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone, since it is a higher
859      * capability
860      */
861     @Test
862     @SmallTest
testSim1HigherCapabilityNoSimsInserted()863     public void testSim1HigherCapabilityNoSimsInserted() {
864         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
865                 false /*isEmergencyOnly*/);
866         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
867                 false /*isEmergencyOnly*/);
868         setDefaultPhone(slot0Phone);
869         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
870         setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT);
871         setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT);
872         // Make Capability the same
873         setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM);
874         setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
875 
876         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
877 
878         assertEquals(slot1Phone, resultPhone);
879     }
880 
881     /**
882      * Prerequisites:
883      * - MSIM Device, no SIMs inserted
884      * - Both SIMs have the same capability (Unknown)
885      *
886      * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone, since it is the first slot.
887      */
888     @Test
889     @SmallTest
testEqualCapabilityNoSimsInserted()890     public void testEqualCapabilityNoSimsInserted() {
891         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
892                 false /*isEmergencyOnly*/);
893         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
894                 false /*isEmergencyOnly*/);
895         setDefaultPhone(slot0Phone);
896         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
897         setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT);
898         setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT);
899         // Make Capability the same
900         setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_UNKNOWN);
901         setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_UNKNOWN);
902 
903         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
904 
905         assertEquals(slot0Phone, resultPhone);
906     }
907 
908     /**
909      * Prerequisites:
910      * - MSIM Device, no SIMs inserted (one ESIM)
911      * - Both SIMs have the same capability (Unknown)
912      *
913      * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone, since it is the first slot.
914      */
915     @Test
916     @SmallTest
testEqualCapabilityNoSimsInserted_WithOneESim()917     public void testEqualCapabilityNoSimsInserted_WithOneESim() {
918         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
919             false /*isEmergencyOnly*/);
920         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
921             false /*isEmergencyOnly*/);
922         setDefaultPhone(slot0Phone);
923         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
924         setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT);
925         when(slot1Phone.getSubId()).thenReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
926         setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
927         // Make Capability the samesvim
928         setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_UNKNOWN);
929         setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_UNKNOWN);
930 
931         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
932 
933         assertEquals(slot0Phone, resultPhone);
934     }
935 
936     /**
937      * Prerequisites:
938      * - MSIM Device, both ESIMS (no profile activated)
939      * - Both phones have the same capability (Unknown)
940      *
941      * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone, since it is the first slot.
942      */
943     @Test
944     @SmallTest
testEqualCapabilityNoSimsInserted_WithTwoESims()945     public void testEqualCapabilityNoSimsInserted_WithTwoESims() {
946         Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
947             false /*isEmergencyOnly*/);
948         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
949             false /*isEmergencyOnly*/);
950         setDefaultPhone(slot0Phone);
951         setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
952         when(slot0Phone.getSubId()).thenReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
953         setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY);
954         when(slot1Phone.getSubId()).thenReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
955         setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
956         // Make Capability the sames
957         setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_UNKNOWN);
958         setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_UNKNOWN);
959 
960         Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
961 
962         assertEquals(slot0Phone, resultPhone);
963     }
964 
965     /**
966      * The modem has returned a temporary error when placing an emergency call on a phone with one
967      * SIM slot.
968      *
969      * Verify that dial is called on the same phone again when retryOutgoingOriginalConnection is
970      * called.
971      */
972     @Test
973     @SmallTest
testRetryOutgoingOriginalConnection_redialTempFailOneSlot()974     public void testRetryOutgoingOriginalConnection_redialTempFailOneSlot() {
975         TestTelephonyConnection c = new TestTelephonyConnection();
976         Phone slot0Phone = c.getPhone();
977         when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID);
978         List<Phone> phones = new ArrayList<>(1);
979         phones.add(slot0Phone);
980         setPhones(phones);
981         c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
982 
983         mTestConnectionService.retryOutgoingOriginalConnection(c,
984                 c.getPhone(), false /*isPermanentFailure*/);
985 
986         // We never need to be notified in telecom that the PhoneAccount has changed, because it
987         // was redialed on the same slot
988         assertEquals(0, c.getNotifyPhoneAccountChangedCount());
989         try {
990             verify(slot0Phone).dial(anyString(), any(), any());
991         } catch (CallStateException e) {
992             // This shouldn't happen
993             fail();
994         }
995     }
996 
997     /**
998      * The modem has returned a permanent failure when placing an emergency call on a phone with one
999      * SIM slot.
1000      *
1001      * Verify that the connection is set to disconnected with an error disconnect cause and dial is
1002      * not called.
1003      */
1004     @Test
1005     @SmallTest
testRetryOutgoingOriginalConnection_redialPermFailOneSlot()1006     public void testRetryOutgoingOriginalConnection_redialPermFailOneSlot() {
1007         TestTelephonyConnection c = new TestTelephonyConnection();
1008         Phone slot0Phone = c.getPhone();
1009         when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID);
1010         List<Phone> phones = new ArrayList<>(1);
1011         phones.add(slot0Phone);
1012         setPhones(phones);
1013         c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
1014 
1015         mTestConnectionService.retryOutgoingOriginalConnection(c,
1016                 c.getPhone(), true /*isPermanentFailure*/);
1017 
1018         // We never need to be notified in telecom that the PhoneAccount has changed, because it
1019         // was never redialed
1020         assertEquals(0, c.getNotifyPhoneAccountChangedCount());
1021         try {
1022             verify(slot0Phone, never()).dial(anyString(), any(), any());
1023         } catch (CallStateException e) {
1024             // This shouldn't happen
1025             fail();
1026         }
1027         assertEquals(c.getState(), android.telecom.Connection.STATE_DISCONNECTED);
1028         assertEquals(c.getDisconnectCause().getCode(), DisconnectCause.ERROR);
1029     }
1030 
1031     /**
1032      * The modem has returned a temporary failure when placing an emergency call on a phone with two
1033      * SIM slots.
1034      *
1035      * Verify that the emergency call is dialed on the other slot and telecom is notified of the new
1036      * PhoneAccount.
1037      */
1038     @Test
1039     @SmallTest
testRetryOutgoingOriginalConnection_redialTempFailTwoSlot()1040     public void testRetryOutgoingOriginalConnection_redialTempFailTwoSlot() {
1041         TestTelephonyConnection c = new TestTelephonyConnection();
1042         Phone slot0Phone = c.getPhone();
1043         when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID);
1044         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
1045                 false /*isEmergencyOnly*/);
1046         setPhonesDialConnection(slot1Phone, c.getOriginalConnection());
1047         c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
1048         List<Phone> phones = new ArrayList<>(2);
1049         phones.add(slot0Phone);
1050         phones.add(slot1Phone);
1051         setPhones(phones);
1052         doReturn(PHONE_ACCOUNT_HANDLE_1).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
1053                 slot0Phone);
1054         doReturn(PHONE_ACCOUNT_HANDLE_2).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
1055                 slot1Phone);
1056 
1057         mTestConnectionService.retryOutgoingOriginalConnection(c,
1058                 c.getPhone(), false /*isPermanentFailure*/);
1059 
1060         // The cache should still contain all of the Phones, since it was a temporary failure.
1061         assertEquals(2, mTestConnectionService.mEmergencyRetryCache.second.size());
1062         // We need to be notified in Telecom that the PhoneAccount has changed, because it was
1063         // redialed on another slot
1064         assertEquals(1, c.getNotifyPhoneAccountChangedCount());
1065         try {
1066             verify(slot1Phone).dial(anyString(), any(), any());
1067         } catch (CallStateException e) {
1068             // This shouldn't happen
1069             fail();
1070         }
1071     }
1072 
1073     /**
1074      * The modem has returned a temporary failure when placing an emergency call on a phone with two
1075      * SIM slots.
1076      *
1077      * Verify that the emergency call is dialed on the other slot and telecom is notified of the new
1078      * PhoneAccount.
1079      */
1080     @Test
1081     @SmallTest
testRetryOutgoingOriginalConnection_redialPermFailTwoSlot()1082     public void testRetryOutgoingOriginalConnection_redialPermFailTwoSlot() {
1083         TestTelephonyConnection c = new TestTelephonyConnection();
1084         Phone slot0Phone = c.getPhone();
1085         when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID);
1086         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
1087                 false /*isEmergencyOnly*/);
1088         setPhonesDialConnection(slot1Phone, c.getOriginalConnection());
1089         c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
1090         List<Phone> phones = new ArrayList<>(2);
1091         phones.add(slot0Phone);
1092         phones.add(slot1Phone);
1093         setPhones(phones);
1094         doReturn(PHONE_ACCOUNT_HANDLE_1).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
1095                 slot0Phone);
1096         doReturn(PHONE_ACCOUNT_HANDLE_2).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
1097                 slot1Phone);
1098 
1099         mTestConnectionService.retryOutgoingOriginalConnection(c,
1100                 c.getPhone(), true /*isPermanentFailure*/);
1101 
1102         // The cache should only contain the slot1Phone.
1103         assertEquals(1, mTestConnectionService.mEmergencyRetryCache.second.size());
1104         // We need to be notified in Telecom that the PhoneAccount has changed, because it was
1105         // redialed on another slot
1106         assertEquals(1, c.getNotifyPhoneAccountChangedCount());
1107         try {
1108             verify(slot1Phone).dial(anyString(), any(), any());
1109         } catch (CallStateException e) {
1110             // This shouldn't happen
1111             fail();
1112         }
1113     }
1114 
1115     /**
1116      * The modem has returned a temporary failure twice while placing an emergency call on a phone
1117      * with two SIM slots.
1118      *
1119      * Verify that the emergency call is dialed on slot 1 and then on slot 0 and telecom is
1120      * notified of this twice.
1121      */
1122     @Test
1123     @SmallTest
testRetryOutgoingOriginalConnection_redialTempFailTwoSlot_twoFailure()1124     public void testRetryOutgoingOriginalConnection_redialTempFailTwoSlot_twoFailure() {
1125         TestTelephonyConnection c = new TestTelephonyConnection();
1126         Phone slot0Phone = c.getPhone();
1127         when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID);
1128         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
1129                 false /*isEmergencyOnly*/);
1130         setPhonesDialConnection(slot1Phone, c.getOriginalConnection());
1131         c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
1132         List<Phone> phones = new ArrayList<>(2);
1133         phones.add(slot0Phone);
1134         phones.add(slot1Phone);
1135         setPhones(phones);
1136         doReturn(PHONE_ACCOUNT_HANDLE_1).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
1137                 slot0Phone);
1138         doReturn(PHONE_ACCOUNT_HANDLE_2).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
1139                 slot1Phone);
1140 
1141         // First Temporary failure
1142         mTestConnectionService.retryOutgoingOriginalConnection(c,
1143                 c.getPhone(), false /*isPermanentFailure*/);
1144         // Set the Phone to the new phone that was just used to dial.
1145         c.setMockPhone(slot1Phone);
1146         // The cache should still contain all of the Phones, since it was a temporary failure.
1147         assertEquals(2, mTestConnectionService.mEmergencyRetryCache.second.size());
1148         // Make sure slot 1 is next in the queue.
1149         assertEquals(slot1Phone, mTestConnectionService.mEmergencyRetryCache.second.peek());
1150         // Second Temporary failure
1151         mTestConnectionService.retryOutgoingOriginalConnection(c,
1152                 c.getPhone(), false /*isPermanentFailure*/);
1153         // Set the Phone to the new phone that was just used to dial.
1154         c.setMockPhone(slot0Phone);
1155         // The cache should still contain all of the Phones, since it was a temporary failure.
1156         assertEquals(2, mTestConnectionService.mEmergencyRetryCache.second.size());
1157         // Make sure slot 0 is next in the queue.
1158         assertEquals(slot0Phone, mTestConnectionService.mEmergencyRetryCache.second.peek());
1159 
1160         // We need to be notified in Telecom that the PhoneAccount has changed, because it was
1161         // redialed on another slot
1162         assertEquals(2, c.getNotifyPhoneAccountChangedCount());
1163         try {
1164             verify(slot0Phone).dial(anyString(), any(), any());
1165             verify(slot1Phone).dial(anyString(), any(), any());
1166         } catch (CallStateException e) {
1167             // This shouldn't happen
1168             fail();
1169         }
1170     }
1171 
1172     /**
1173      * The modem has returned a permanent failure twice while placing an emergency call on a phone
1174      * with two SIM slots.
1175      *
1176      * Verify that the emergency call is dialed on slot 1 and then disconnected and telecom is
1177      * notified of the change to slot 1.
1178      */
1179     @Test
1180     @SmallTest
testRetryOutgoingOriginalConnection_redialPermFailTwoSlot_twoFailure()1181     public void testRetryOutgoingOriginalConnection_redialPermFailTwoSlot_twoFailure() {
1182         TestTelephonyConnection c = new TestTelephonyConnection();
1183         Phone slot0Phone = c.getPhone();
1184         when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID);
1185         Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
1186                 false /*isEmergencyOnly*/);
1187         setPhonesDialConnection(slot1Phone, c.getOriginalConnection());
1188         c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
1189         List<Phone> phones = new ArrayList<>(2);
1190         phones.add(slot0Phone);
1191         phones.add(slot1Phone);
1192         setPhones(phones);
1193         doReturn(PHONE_ACCOUNT_HANDLE_1).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
1194                 slot0Phone);
1195         doReturn(PHONE_ACCOUNT_HANDLE_2).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
1196                 slot1Phone);
1197 
1198         // First Permanent failure
1199         mTestConnectionService.retryOutgoingOriginalConnection(c,
1200                 c.getPhone(), true /*isPermanentFailure*/);
1201         // Set the Phone to the new phone that was just used to dial.
1202         c.setMockPhone(slot1Phone);
1203         // The cache should only contain one phone
1204         assertEquals(1, mTestConnectionService.mEmergencyRetryCache.second.size());
1205         // Make sure slot 1 is next in the queue.
1206         assertEquals(slot1Phone, mTestConnectionService.mEmergencyRetryCache.second.peek());
1207         // Second Permanent failure
1208         mTestConnectionService.retryOutgoingOriginalConnection(c,
1209                 c.getPhone(), true /*isPermanentFailure*/);
1210         // The cache should be empty
1211         assertEquals(true, mTestConnectionService.mEmergencyRetryCache.second.isEmpty());
1212 
1213         assertEquals(c.getState(), android.telecom.Connection.STATE_DISCONNECTED);
1214         assertEquals(c.getDisconnectCause().getCode(), DisconnectCause.ERROR);
1215         // We need to be notified in Telecom that the PhoneAccount has changed, because it was
1216         // redialed on another slot
1217         assertEquals(1, c.getNotifyPhoneAccountChangedCount());
1218         try {
1219             verify(slot1Phone).dial(anyString(), any(), any());
1220             verify(slot0Phone, never()).dial(anyString(), any(), any());
1221         } catch (CallStateException e) {
1222             // This shouldn't happen
1223             fail();
1224         }
1225     }
1226 
1227     @Test
1228     @SmallTest
testSuppServiceNotification()1229     public void testSuppServiceNotification() {
1230         TestTelephonyConnection c = new TestTelephonyConnection();
1231 
1232         // We need to set the original connection to cause the supp service notification
1233         // registration to occur.
1234         Phone phone = c.getPhone();
1235         c.setOriginalConnection(c.getOriginalConnection());
1236         doReturn(mContext).when(phone).getContext();
1237 
1238         // When the registration occurs, we'll capture the handler and message so we can post our
1239         // own messages to it.
1240         ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
1241         ArgumentCaptor<Integer> messageCaptor = ArgumentCaptor.forClass(Integer.class);
1242         verify(phone).registerForSuppServiceNotification(handlerCaptor.capture(),
1243                 messageCaptor.capture(), any());
1244         Handler handler = handlerCaptor.getValue();
1245         int message = messageCaptor.getValue();
1246 
1247         // With the handler and message now known, we'll post a supp service notification.
1248         AsyncResult result = getSuppServiceNotification(
1249                 SuppServiceNotification.NOTIFICATION_TYPE_CODE_1,
1250                 SuppServiceNotification.CODE_1_CALL_FORWARDED);
1251         handler.obtainMessage(message, result).sendToTarget();
1252         waitForHandlerAction(handler, TIMEOUT_MS);
1253 
1254         assertTrue(c.getLastConnectionEvents().contains(TelephonyManager.EVENT_CALL_FORWARDED));
1255 
1256         // With the handler and message now known, we'll post a supp service notification.
1257         result = getSuppServiceNotification(
1258                 SuppServiceNotification.NOTIFICATION_TYPE_CODE_1,
1259                 SuppServiceNotification.CODE_1_CALL_IS_WAITING);
1260         handler.obtainMessage(message, result).sendToTarget();
1261         waitForHandlerAction(handler, TIMEOUT_MS);
1262 
1263         // We we want the 3rd event since the forwarding one above sends 2.
1264         assertEquals(c.getLastConnectionEvents().get(2),
1265                 TelephonyManager.EVENT_SUPPLEMENTARY_SERVICE_NOTIFICATION);
1266         Bundle extras = c.getLastConnectionEventExtras().get(2);
1267         assertEquals(SuppServiceNotification.NOTIFICATION_TYPE_CODE_1,
1268                 extras.getInt(TelephonyManager.EXTRA_NOTIFICATION_TYPE));
1269         assertEquals(SuppServiceNotification.CODE_1_CALL_IS_WAITING,
1270                 extras.getInt(TelephonyManager.EXTRA_NOTIFICATION_CODE));
1271     }
1272 
1273     /**
1274      * Test that the TelephonyConnectionService successfully performs a DDS switch before a call
1275      * when we are not roaming and the carrier only supports SUPL over the data plane.
1276      */
1277     @Test
1278     @SmallTest
testCreateOutgoingEmergencyConnection_delayDial_carrierconfig_dds()1279     public void testCreateOutgoingEmergencyConnection_delayDial_carrierconfig_dds() {
1280         // Setup test to not support SUPL on the non-DDS subscription
1281         doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
1282         getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
1283                 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
1284                 null);
1285         getTestContext().getCarrierConfig(0 /*subId*/).putInt(
1286                 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
1287                 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY);
1288         getTestContext().getCarrierConfig(0 /*subId*/).putString(
1289                 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "150");
1290 
1291         Phone testPhone = setupConnectionServiceForDelayDial(
1292                 false /* isRoaming */, false /* setOperatorName */, null /* operator long name*/,
1293                         null /* operator short name */, null /* operator numeric name */);
1294         verify(mPhoneSwitcher).overrideDefaultDataForEmergency(eq(0) /*phoneId*/ ,
1295                 eq(150) /*extensionTime*/, any());
1296     }
1297 
1298     /**
1299      * Test that the TelephonyConnectionService successfully turns radio on before placing the
1300      * emergency call.
1301      */
1302     @Test
1303     @SmallTest
testCreateOutgoingEmerge_exitingApm_disconnected()1304     public void testCreateOutgoingEmerge_exitingApm_disconnected() {
1305         when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
1306         Phone testPhone = setupConnectionServiceInApm();
1307 
1308         ArgumentCaptor<RadioOnStateListener.Callback> callback =
1309                 ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
1310         verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
1311                 eq(testPhone), eq(false), eq(0));
1312 
1313         assertFalse(callback.getValue()
1314                 .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
1315         when(mSST.isRadioOn()).thenReturn(true);
1316         assertTrue(callback.getValue()
1317                 .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
1318 
1319         mConnection.setDisconnected(null);
1320         callback.getValue().onComplete(null, true);
1321         for (Phone phone : mPhoneFactoryProxy.getPhones()) {
1322             verify(phone).setRadioPower(true, false, false, true);
1323         }
1324     }
1325 
1326     /**
1327      * Test that the TelephonyConnectionService successfully turns radio on before placing the
1328      * emergency call.
1329      */
1330     @Test
1331     @SmallTest
testCreateOutgoingEmergencyConnection_exitingApm_placeCall()1332     public void testCreateOutgoingEmergencyConnection_exitingApm_placeCall() {
1333         when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
1334         Phone testPhone = setupConnectionServiceInApm();
1335 
1336         ArgumentCaptor<RadioOnStateListener.Callback> callback =
1337                 ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
1338         verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
1339                 eq(testPhone), eq(false), eq(0));
1340 
1341         assertFalse(callback.getValue()
1342                 .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
1343         when(mSST.isRadioOn()).thenReturn(true);
1344         assertTrue(callback.getValue()
1345                 .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
1346 
1347         callback.getValue().onComplete(null, true);
1348 
1349         try {
1350             doAnswer(invocation -> null).when(mContext).startActivityAsUser(any(), any());
1351             verify(testPhone).dial(anyString(), any(), any());
1352         } catch (CallStateException e) {
1353             // This shouldn't happen
1354             fail();
1355         }
1356         verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), anyBoolean());
1357     }
1358 
1359     /**
1360      * Test that the TelephonyConnectionService successfully dials an outgoing normal routed
1361      * emergency call on an in-service sim.
1362      */
1363     @Test
1364     @SmallTest
testCreateOutgoingConnectionForNormalRoutedEmergencyCall()1365     public void testCreateOutgoingConnectionForNormalRoutedEmergencyCall()
1366             throws CallStateException {
1367         // A whole load of annoying mocks to set up to test this scenario.
1368         // We'll purposely try to start the call on the limited service phone.
1369         ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
1370                 .setAccountHandle(PHONE_ACCOUNT_HANDLE_1)
1371                 .setAddress(Uri.fromParts(PhoneAccount.SCHEME_TEL, NORMAL_ROUTED_EMERGENCY_NUMBER,
1372                         null))
1373                 .build();
1374 
1375         // First phone is in limited service.
1376         Phone testPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_EMERGENCY_ONLY,
1377                 true /*isEmergencyOnly*/);
1378         doReturn(ImsRegistrationImplBase.REGISTRATION_TECH_LTE).when(testPhone0)
1379                 .getImsRegistrationTech();
1380         doReturn(0).when(testPhone0).getSubId();
1381         setupMockEmergencyNumbers(testPhone0, List.of(MOCK_NORMAL_NUMBER,
1382                 MOCK_NORMAL_NUMBER_WITH_UNKNOWN_ROUTING, MOCK_EMERGENCY_NUMBER));
1383 
1384         // Second phone is in full service; this is ultimately the one we want to pick.
1385         Phone testPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_IN_SERVICE,
1386                 false /*isEmergencyOnly*/);
1387         doReturn(ImsRegistrationImplBase.REGISTRATION_TECH_LTE).when(testPhone1)
1388                 .getImsRegistrationTech();
1389         doReturn(1).when(testPhone1).getSubId();
1390         setupMockEmergencyNumbers(testPhone1, List.of(MOCK_NORMAL_NUMBER,
1391                 MOCK_NORMAL_NUMBER_WITH_UNKNOWN_ROUTING, MOCK_EMERGENCY_NUMBER));
1392 
1393         // Make sure both phones are going to prefer in service for normal routed ecalls.
1394         doReturn(true).when(testPhone0).shouldPreferInServiceSimForNormalRoutedEmergencyCall();
1395         doReturn(true).when(testPhone1).shouldPreferInServiceSimForNormalRoutedEmergencyCall();
1396 
1397         // A whole load of other stuff that needs to be setup for this to work.
1398         doReturn(GSM_PHONE).when(testPhone0).getPhoneType();
1399         doReturn(GSM_PHONE).when(testPhone1).getPhoneType();
1400         List<Phone> phones = new ArrayList<>(2);
1401         doReturn(true).when(testPhone0).isRadioOn();
1402         doReturn(true).when(testPhone1).isRadioOn();
1403         phones.add(testPhone0);
1404         phones.add(testPhone1);
1405         setPhones(phones);
1406         doReturn(0).when(mPhoneUtilsProxy).getSubIdForPhoneAccountHandle(
1407                 eq(PHONE_ACCOUNT_HANDLE_1));
1408         doReturn(1).when(mPhoneUtilsProxy).getSubIdForPhoneAccountHandle(
1409                 eq(PHONE_ACCOUNT_HANDLE_2));
1410         setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_1, testPhone0);
1411         setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_2, testPhone1);
1412         setupDeviceConfig(testPhone0, testPhone1, 0);
1413         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(
1414                 eq(NORMAL_ROUTED_EMERGENCY_NUMBER));
1415         HashMap<Integer, List<EmergencyNumber>> emergencyNumbers = new HashMap<>(1);
1416         List<EmergencyNumber> numbers = new ArrayList<>();
1417         numbers.add(MOCK_EMERGENCY_NUMBER);
1418         numbers.add(MOCK_NORMAL_NUMBER);
1419         numbers.add(MOCK_NORMAL_NUMBER_WITH_UNKNOWN_ROUTING);
1420         emergencyNumbers.put(0 /*subId*/, numbers);
1421         doReturn(emergencyNumbers).when(mTelephonyManagerProxy).getCurrentEmergencyNumberList();
1422         doReturn(2).when(mTelephonyManagerProxy).getPhoneCount();
1423 
1424         // All of that for... this.
1425         mConnection = mTestConnectionService.onCreateOutgoingConnection(
1426                 PHONE_ACCOUNT_HANDLE_1, connectionRequest);
1427         assertNotNull("test connection was not set up correctly.", mConnection);
1428 
1429         // Lets make sure we DID try to place the call on phone 1, which is the in service phone.
1430         verify(testPhone1).dial(anyString(), any(DialArgs.class), any(Consumer.class));
1431         // And make sure we DID NOT try to place the call on phone 0, which is in limited service.
1432         verify(testPhone0, never()).dial(anyString(), any(DialArgs.class), any(Consumer.class));
1433     }
1434 
1435     /**
1436      * Test that the TelephonyConnectionService successfully turns satellite off before placing the
1437      * emergency call.
1438      */
1439     @Test
1440     @SmallTest
testCreateOutgoingEmergencyConnection_exitingSatellite_placeCall()1441     public void testCreateOutgoingEmergencyConnection_exitingSatellite_placeCall() {
1442         when(mSatelliteController.isSatelliteEnabledOrBeingEnabled()).thenReturn(true);
1443         doReturn(true).when(mMockResources).getBoolean(anyInt());
1444         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(
1445                 anyString());
1446         Phone testPhone = setupConnectionServiceInApm();
1447 
1448         ArgumentCaptor<RadioOnStateListener.Callback> callback =
1449                 ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
1450         verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
1451                 eq(testPhone), eq(false), eq(0));
1452 
1453         assertFalse(callback.getValue()
1454                 .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
1455         when(mSST.isRadioOn()).thenReturn(true);
1456         assertFalse(callback.getValue()
1457                 .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
1458         when(mSatelliteController.isSatelliteEnabledOrBeingEnabled()).thenReturn(false);
1459         assertTrue(callback.getValue()
1460                 .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
1461 
1462         callback.getValue().onComplete(null, true);
1463 
1464         try {
1465             doAnswer(invocation -> null).when(mContext).startActivityAsUser(any(), any());
1466             verify(testPhone).dial(anyString(), any(), any());
1467         } catch (CallStateException e) {
1468             // This shouldn't happen
1469             fail();
1470         }
1471         verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), anyBoolean());
1472     }
1473 
1474     /**
1475      * Test that the TelephonyConnectionService successfully placing the emergency call based on
1476      * CarrierRoaming mode of Satellite.
1477      */
1478     @Test
1479     @SmallTest
testCreateOutgoingEmergencyConnection_exitingSatellite_EmergencySatellite()1480     public void testCreateOutgoingEmergencyConnection_exitingSatellite_EmergencySatellite()
1481             throws Exception {
1482         doReturn(true).when(mFeatureFlags).carrierRoamingNbIotNtn();
1483         doReturn(true).when(mSatelliteController).isSatelliteEnabledOrBeingEnabled();
1484 
1485         // Set config_turn_off_non_emergency_nb_iot_ntn_satellite_for_emergency_call as true
1486         doReturn(true).when(mMockResources).getBoolean(anyInt());
1487         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
1488         doReturn(false).when(mSatelliteController).isDemoModeEnabled();
1489 
1490         // Satellite is not for emergency, allow EMC
1491         doReturn(false).when(mSatelliteController).getRequestIsEmergency();
1492         // Setup outgoing emergency call
1493         setupConnectionServiceInApm();
1494 
1495         // Verify emergency call go through
1496         assertNull(mConnection.getDisconnectCause());
1497     }
1498 
1499     @Test
1500     @SmallTest
testCreateOutgoingEmergencyConnection_exitingSatellite_OEM()1501     public void testCreateOutgoingEmergencyConnection_exitingSatellite_OEM() throws Exception {
1502         doReturn(true).when(mFeatureFlags).carrierRoamingNbIotNtn();
1503         doReturn(true).when(mSatelliteController).isSatelliteEnabledOrBeingEnabled();
1504 
1505         // Set config_turn_off_oem_enabled_satellite_during_emergency_call as false
1506         doReturn(false).when(mMockResources).getBoolean(anyInt());
1507         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
1508         doReturn(false).when(mSatelliteController).isDemoModeEnabled();
1509 
1510         // Satellite is for emergency
1511         doReturn(true).when(mSatelliteController).getRequestIsEmergency();
1512         doReturn(1).when(mSatelliteController).getSelectedSatelliteSubId();
1513         SubscriptionManagerService isub = mock(SubscriptionManagerService.class);
1514         replaceInstance(SubscriptionManagerService.class, "sInstance", null, isub);
1515         SubscriptionInfoInternal info = mock(SubscriptionInfoInternal.class);
1516         doReturn(info).when(isub).getSubscriptionInfoInternal(1);
1517 
1518         // Setup outgoing emergency call
1519         setupConnectionServiceInApm();
1520 
1521         // Verify DisconnectCause which not allows emergency call
1522         assertNotNull(mConnection.getDisconnectCause());
1523         assertEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
1524                 mConnection.getDisconnectCause().getTelephonyDisconnectCause());
1525 
1526         // OEM: config_turn_off_oem_enabled_satellite_during_emergency_call = true
1527         doReturn(1).when(info).getOnlyNonTerrestrialNetwork();
1528         doReturn(true).when(mMockResources).getBoolean(anyInt());
1529         // Setup outgoing emergency call
1530         setupConnectionServiceInApm();
1531 
1532         // Verify emergency call go through
1533         assertNull(mConnection.getDisconnectCause());
1534     }
1535 
1536     @Test
1537     @SmallTest
testCreateOutgoingEmergencyConnection_exitingSatellite_Carrier()1538     public void testCreateOutgoingEmergencyConnection_exitingSatellite_Carrier() throws Exception {
1539         doReturn(true).when(mFeatureFlags).carrierRoamingNbIotNtn();
1540         doReturn(true).when(mSatelliteController).isSatelliteEnabledOrBeingEnabled();
1541 
1542         // Set config_turn_off_oem_enabled_satellite_during_emergency_call as false
1543         doReturn(false).when(mMockResources).getBoolean(anyInt());
1544         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
1545         doReturn(false).when(mSatelliteController).isDemoModeEnabled();
1546 
1547         // Satellite is for emergency
1548         doReturn(true).when(mSatelliteController).getRequestIsEmergency();
1549         doReturn(1).when(mSatelliteController).getSelectedSatelliteSubId();
1550         SubscriptionManagerService isub = mock(SubscriptionManagerService.class);
1551         replaceInstance(SubscriptionManagerService.class, "sInstance", null, isub);
1552         SubscriptionInfoInternal info = mock(SubscriptionInfoInternal.class);
1553         doReturn(info).when(isub).getSubscriptionInfoInternal(1);
1554 
1555         // Carrier: shouldTurnOffCarrierSatelliteForEmergencyCall = false
1556         doReturn(0).when(info).getOnlyNonTerrestrialNetwork();
1557         doReturn(false).when(mSatelliteController).shouldTurnOffCarrierSatelliteForEmergencyCall();
1558         setupConnectionServiceInApm();
1559 
1560         // Verify DisconnectCause which not allows emergency call
1561         assertNotNull(mConnection.getDisconnectCause());
1562         assertEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
1563                 mConnection.getDisconnectCause().getTelephonyDisconnectCause());
1564 
1565         // Carrier: shouldTurnOffCarrierSatelliteForEmergencyCall = true
1566         doReturn(true).when(mMockResources).getBoolean(anyInt());
1567         doReturn(true).when(mSatelliteController).shouldTurnOffCarrierSatelliteForEmergencyCall();
1568         setupConnectionServiceInApm();
1569 
1570         // Verify emergency call go through
1571         assertNull(mConnection.getDisconnectCause());
1572     }
1573 
1574     @Test
1575     @SmallTest
testCreateOutgoingEmergencyConnection_NonEmergencySatelliteSession()1576     public void testCreateOutgoingEmergencyConnection_NonEmergencySatelliteSession() {
1577         doReturn(true).when(mFeatureFlags).carrierRoamingNbIotNtn();
1578         doReturn(true).when(mSatelliteController).isSatelliteEnabledOrBeingEnabled();
1579 
1580         // Set config_turn_off_non_emergency_nb_iot_ntn_satellite_for_emergency_call as false
1581         doReturn(false).when(mMockResources).getBoolean(anyInt());
1582         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
1583         doReturn(false).when(mSatelliteController).isDemoModeEnabled();
1584 
1585         // Satellite is for emergency
1586         doReturn(false).when(mSatelliteController).getRequestIsEmergency();
1587 
1588         setupConnectionServiceInApm();
1589 
1590         // Verify DisconnectCause which not allows emergency call
1591         assertNotNull(mConnection.getDisconnectCause());
1592         assertEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
1593                 mConnection.getDisconnectCause().getTelephonyDisconnectCause());
1594     }
1595 
1596     /**
1597      * Test that the TelephonyConnectionService successfully turns radio on before placing the
1598      * call when radio off because bluetooth on and wifi calling is not enabled
1599      */
1600     @Test
1601     @SmallTest
testCreateOutgoingCall_turnOnRadio_bluetoothOn()1602     public void testCreateOutgoingCall_turnOnRadio_bluetoothOn() {
1603         doReturn(true).when(mDeviceState).isRadioPowerDownAllowedOnBluetooth(any());
1604         doReturn(PhoneConstants.CELL_ON_FLAG).when(mDeviceState).getCellOnStatus(any());
1605         Phone testPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_POWER_OFF,
1606                 false /*isEmergencyOnly*/);
1607         Phone testPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_POWER_OFF,
1608                 false /*isEmergencyOnly*/);
1609         doReturn(false).when(testPhone0).isRadioOn();
1610         doReturn(false).when(testPhone0).isWifiCallingEnabled();
1611         doReturn(false).when(testPhone1).isRadioOn();
1612         doReturn(false).when(testPhone1).isWifiCallingEnabled();
1613         List<Phone> phones = new ArrayList<>(2);
1614         phones.add(testPhone0);
1615         phones.add(testPhone1);
1616         setPhones(phones);
1617         setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_1, testPhone0);
1618         ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
1619                 .setAccountHandle(PHONE_ACCOUNT_HANDLE_1)
1620                 .setAddress(TEST_ADDRESS)
1621                 .build();
1622         mConnection = mTestConnectionService.onCreateOutgoingConnection(
1623                 PHONE_ACCOUNT_HANDLE_1, connectionRequest);
1624 
1625         verify(mRadioOnHelper).triggerRadioOnAndListen(any(), eq(false),
1626                 eq(testPhone0), eq(false), eq(0));
1627     }
1628 
1629     /**
1630      * Test that the TelephonyConnectionService successfully turns radio on before placing the
1631      * call when phone is null, radio off because bluetooth on and wifi calling is not enabled
1632      */
1633     @Test
1634     @SmallTest
testCreateOutgoingCall_forWearWatch_whenPhoneIsNull()1635     public void testCreateOutgoingCall_forWearWatch_whenPhoneIsNull() {
1636         doReturn(-1).when(mPhoneUtilsProxy).getSubIdForPhoneAccountHandle(any());
1637         doReturn(true).when(mDeviceState).isRadioPowerDownAllowedOnBluetooth(any());
1638         doReturn(PhoneConstants.CELL_ON_FLAG).when(mDeviceState).getCellOnStatus(any());
1639         Phone testPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_POWER_OFF,
1640                 false /*isEmergencyOnly*/);
1641         Phone testPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_POWER_OFF,
1642                 false /*isEmergencyOnly*/);
1643         doReturn(false).when(testPhone0).isRadioOn();
1644         doReturn(false).when(testPhone0).isWifiCallingEnabled();
1645         doReturn(false).when(testPhone1).isRadioOn();
1646         doReturn(false).when(testPhone1).isWifiCallingEnabled();
1647         List<Phone> phones = new ArrayList<>(2);
1648         phones.add(testPhone0);
1649         phones.add(testPhone1);
1650         setPhones(phones);
1651         setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_1, testPhone0);
1652         ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
1653                 .setAccountHandle(PHONE_ACCOUNT_HANDLE_1)
1654                 .setAddress(TEST_ADDRESS)
1655                 .build();
1656         mConnection = mTestConnectionService.onCreateOutgoingConnection(
1657                 PHONE_ACCOUNT_HANDLE_1, connectionRequest);
1658 
1659         verify(mRadioOnHelper).triggerRadioOnAndListen(any(), eq(false),
1660                 eq(testPhone0), eq(false), eq(0));
1661     }
1662 
1663     /**
1664      * Test that the TelephonyConnectionService will not turns radio on before placing the
1665      * call when radio off because bluetooth on and wifi calling is enabled
1666      */
1667     @Test
1668     @SmallTest
testCreateOutgoingCall_notTurnOnRadio_bluetoothOnWifiCallingEnabled()1669     public void testCreateOutgoingCall_notTurnOnRadio_bluetoothOnWifiCallingEnabled() {
1670         doReturn(true).when(mDeviceState).isRadioPowerDownAllowedOnBluetooth(any());
1671         doReturn(PhoneConstants.CELL_ON_FLAG).when(mDeviceState).getCellOnStatus(any());
1672         Phone testPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_POWER_OFF,
1673                 false /*isEmergencyOnly*/);
1674         Phone testPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_POWER_OFF,
1675                 false /*isEmergencyOnly*/);
1676         doReturn(false).when(testPhone0).isRadioOn();
1677         doReturn(true).when(testPhone0).isWifiCallingEnabled();
1678         doReturn(false).when(testPhone1).isRadioOn();
1679         doReturn(true).when(testPhone1).isWifiCallingEnabled();
1680         List<Phone> phones = new ArrayList<>(2);
1681         phones.add(testPhone0);
1682         phones.add(testPhone1);
1683         setPhones(phones);
1684         setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_1, testPhone0);
1685         ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
1686                 .setAccountHandle(PHONE_ACCOUNT_HANDLE_1)
1687                 .setAddress(TEST_ADDRESS)
1688                 .build();
1689         mConnection = mTestConnectionService.onCreateOutgoingConnection(
1690                 PHONE_ACCOUNT_HANDLE_1, connectionRequest);
1691 
1692         verify(mRadioOnHelper, times(0)).triggerRadioOnAndListen(any(),
1693                 eq(true), eq(testPhone0), eq(false), eq(0));
1694     }
1695 
1696     /**
1697      * Test that the TelephonyConnectionService does not perform a DDS switch when the carrier
1698      * supports control-plane fallback.
1699      */
1700     @Test
1701     @SmallTest
testCreateOutgoingEmergencyConnection_delayDial_nocarrierconfig()1702     public void testCreateOutgoingEmergencyConnection_delayDial_nocarrierconfig() {
1703         // Setup test to not support SUPL on the non-DDS subscription
1704         doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
1705         getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
1706                 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
1707                 null);
1708         getTestContext().getCarrierConfig(0 /*subId*/).putInt(
1709                 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
1710                 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK);
1711         getTestContext().getCarrierConfig(0 /*subId*/).putString(
1712                 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
1713 
1714         Phone testPhone = setupConnectionServiceForDelayDial(
1715                 false /* isRoaming */, false /* setOperatorName */, null /* operator long name*/,
1716                         null /* operator short name */, null /* operator numeric name */);
1717         verify(mPhoneSwitcher, never()).overrideDefaultDataForEmergency(anyInt(), anyInt(), any());
1718     }
1719 
1720     /**
1721      * Test that the TelephonyConnectionService does not perform a DDS switch when the carrier
1722      * supports control-plane fallback.
1723      */
1724     @Test
1725     @SmallTest
testCreateOutgoingEmergencyConnection_delayDial_supportsuplondds()1726     public void testCreateOutgoingEmergencyConnection_delayDial_supportsuplondds() {
1727         // If the non-DDS supports SUPL, don't switch data
1728         doReturn(false).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
1729         getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
1730                 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
1731                 null);
1732         getTestContext().getCarrierConfig(0 /*subId*/).putInt(
1733                 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
1734                 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY);
1735         getTestContext().getCarrierConfig(0 /*subId*/).putString(
1736                 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
1737 
1738         Phone testPhone = setupConnectionServiceForDelayDial(
1739                 false /* isRoaming */, false /* setOperatorName */, null /* operator long name*/,
1740                          null /* operator short name */, null /* operator numeric name */);
1741         verify(mPhoneSwitcher, never()).overrideDefaultDataForEmergency(anyInt(), anyInt(), any());
1742     }
1743 
1744     /**
1745      * Test that the TelephonyConnectionService does not perform a DDS switch when the carrier does
1746      * not support control-plane fallback CarrierConfig while roaming.
1747      */
1748     @Test
1749     @SmallTest
testCreateOutgoingEmergencyConnection_delayDial_roaming_nocarrierconfig()1750     public void testCreateOutgoingEmergencyConnection_delayDial_roaming_nocarrierconfig() {
1751         // Setup test to not support SUPL on the non-DDS subscription
1752         doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
1753         getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
1754                 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
1755                 null);
1756         getTestContext().getCarrierConfig(0 /*subId*/).putInt(
1757                 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
1758                 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY);
1759         getTestContext().getCarrierConfig(0 /*subId*/).putString(
1760                 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
1761 
1762         Phone testPhone = setupConnectionServiceForDelayDial(
1763                 true /* isRoaming */, false /* setOperatorName */, null /* operator long name*/,
1764                          null /* operator short name */, null /* operator numeric name */);
1765         verify(mPhoneSwitcher, never()).overrideDefaultDataForEmergency(anyInt(), anyInt(), any());
1766     }
1767 
1768     /**
1769      * Test that the TelephonyConnectionService does perform a DDS switch even though the carrier
1770      * supports control-plane fallback CarrierConfig and the roaming partner is configured to look
1771      * like a home network.
1772      */
1773     @Test
1774     @SmallTest
testCreateOutgoingEmergencyConnection_delayDial_roamingcarrierconfig()1775     public void testCreateOutgoingEmergencyConnection_delayDial_roamingcarrierconfig() {
1776         doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
1777         // Setup voice roaming scenario
1778         String testRoamingOperator = "001001";
1779         // Setup test to not support SUPL on the non-DDS subscription
1780         String[] roamingPlmns = new String[1];
1781         roamingPlmns[0] = testRoamingOperator;
1782         getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
1783                 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
1784                 roamingPlmns);
1785         getTestContext().getCarrierConfig(0 /*subId*/).putInt(
1786                 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
1787                 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK);
1788         getTestContext().getCarrierConfig(0 /*subId*/).putString(
1789                 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
1790 
1791         Phone testPhone = setupConnectionServiceForDelayDial(
1792                 false /* isRoaming */, true /* setOperatorName */,
1793                         "TestTel" /* operator long name*/, "TestTel" /* operator short name */,
1794                                 testRoamingOperator /* operator numeric name */);
1795         verify(mPhoneSwitcher).overrideDefaultDataForEmergency(eq(0) /*phoneId*/ ,
1796                 eq(0) /*extensionTime*/, any());
1797     }
1798 
1799     /**
1800      * Test that the TelephonyConnectionService does perform a DDS switch even though the carrier
1801      * supports control-plane fallback CarrierConfig if we are roaming and the roaming partner is
1802      * configured to use data plane only SUPL.
1803      */
1804     @Test
1805     @SmallTest
testCreateOutgoingEmergencyConnection_delayDial__roaming_roamingcarrierconfig()1806     public void testCreateOutgoingEmergencyConnection_delayDial__roaming_roamingcarrierconfig() {
1807         // Setup test to not support SUPL on the non-DDS subscription
1808         doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
1809         // Setup voice roaming scenario
1810         String testRoamingOperator = "001001";
1811         String[] roamingPlmns = new String[1];
1812         roamingPlmns[0] = testRoamingOperator;
1813         getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
1814                 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
1815                 roamingPlmns);
1816         getTestContext().getCarrierConfig(0 /*subId*/).putInt(
1817                 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
1818                 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK);
1819         getTestContext().getCarrierConfig(0 /*subId*/).putString(
1820                 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
1821 
1822         Phone testPhone = setupConnectionServiceForDelayDial(
1823                 false /* isRoaming */, true /* setOperatorName */,
1824                         "TestTel" /* operator long name*/, "TestTel" /* operator short name */,
1825                                 testRoamingOperator /* operator numeric name */);
1826         verify(mPhoneSwitcher).overrideDefaultDataForEmergency(eq(0) /*phoneId*/ ,
1827                 eq(0) /*extensionTime*/, any());
1828     }
1829 
1830     /**
1831      * Verifies for an incoming call on the same SIM that we don't set
1832      * {@link android.telecom.Connection#EXTRA_ANSWERING_DROPS_FG_CALL} on the incoming call extras.
1833      * @throws Exception
1834      */
1835     @Test
1836     @SmallTest
testIncomingDoesntRequestDisconnect()1837     public void testIncomingDoesntRequestDisconnect() throws Exception {
1838         setupForCallTest();
1839 
1840         mBinderStub.createConnection(PHONE_ACCOUNT_HANDLE_1, "TC@1",
1841                 new ConnectionRequest(PHONE_ACCOUNT_HANDLE_1, Uri.parse("tel:16505551212"),
1842                         new Bundle()),
1843                 true, false, null);
1844         waitForHandlerAction(mTestConnectionService.getHandler(), TIMEOUT_MS);
1845         assertEquals(1, mTestConnectionService.getAllConnections().size());
1846 
1847         // Make sure the extras do not indicate that it answering will disconnect another call.
1848         android.telecom.Connection connection = (android.telecom.Connection)
1849                 mTestConnectionService.getAllConnections().toArray()[0];
1850         assertFalse(connection.getExtras() != null && connection.getExtras().containsKey(
1851                 android.telecom.Connection.EXTRA_ANSWERING_DROPS_FG_CALL));
1852     }
1853 
1854     /**
1855      * Verifies where there is another call on the same sub, we don't set
1856      * {@link android.telecom.Connection#EXTRA_ANSWERING_DROPS_FG_CALL} on the incoming call extras.
1857      * @throws Exception
1858      */
1859     @Test
1860     @SmallTest
testSecondCallSameSubWontDisconnect()1861     public void testSecondCallSameSubWontDisconnect() throws Exception {
1862         // Previous test gets us into a good enough state
1863         testIncomingDoesntRequestDisconnect();
1864 
1865         when(mCall.getState()).thenReturn(Call.State.ACTIVE);
1866         when(mCall2.getState()).thenReturn(Call.State.WAITING);
1867         when(mCall2.getLatestConnection()).thenReturn(mInternalConnection2);
1868         when(mPhone0.getRingingCall()).thenReturn(mCall2);
1869 
1870         mBinderStub.createConnection(PHONE_ACCOUNT_HANDLE_1, "TC@2",
1871                 new ConnectionRequest(PHONE_ACCOUNT_HANDLE_1, Uri.parse("tel:16505551213"),
1872                         new Bundle()),
1873                 true, false, null);
1874         waitForHandlerAction(mTestConnectionService.getHandler(), TIMEOUT_MS);
1875         assertEquals(2, mTestConnectionService.getAllConnections().size());
1876 
1877         // None of the connections should have the extra set.
1878         assertEquals(0, mTestConnectionService.getAllConnections().stream()
1879                 .filter(c -> c.getExtras() != null && c.getExtras().containsKey(
1880                         android.telecom.Connection.EXTRA_ANSWERING_DROPS_FG_CALL))
1881                 .count());
1882     }
1883 
1884     /**
1885      * Verifies where there is another call on a different sub, we set
1886      * {@link android.telecom.Connection#EXTRA_ANSWERING_DROPS_FG_CALL} on the incoming call extras.
1887      * @throws Exception
1888      */
1889     @Test
1890     @SmallTest
testSecondCallDifferentSubWillDisconnect()1891     public void testSecondCallDifferentSubWillDisconnect() throws Exception {
1892         // Previous test gets us into a good enough state
1893         testIncomingDoesntRequestDisconnect();
1894 
1895         when(mCall.getState()).thenReturn(Call.State.ACTIVE);
1896         when(mCall2.getState()).thenReturn(Call.State.WAITING);
1897         when(mCall2.getLatestConnection()).thenReturn(mInternalConnection2);
1898         // At this point the call is ringing on the second phone.
1899         when(mPhone0.getRingingCall()).thenReturn(null);
1900         when(mPhone1.getRingingCall()).thenReturn(mCall2);
1901 
1902         mBinderStub.createConnection(PHONE_ACCOUNT_HANDLE_2, "TC@2",
1903                 new ConnectionRequest(PHONE_ACCOUNT_HANDLE_2, Uri.parse("tel:16505551213"),
1904                         new Bundle()),
1905                 true, false, null);
1906         waitForHandlerAction(mTestConnectionService.getHandler(), TIMEOUT_MS);
1907         assertEquals(2, mTestConnectionService.getAllConnections().size());
1908 
1909         // The incoming connection should have the extra set.
1910         assertEquals(1, mTestConnectionService.getAllConnections().stream()
1911                 .filter(c -> c.getExtras() != null && c.getExtras().containsKey(
1912                         android.telecom.Connection.EXTRA_ANSWERING_DROPS_FG_CALL))
1913                 .count());
1914     }
1915 
1916     /**
1917      * For virtual DSDA-enabled devices, verifies where there is another call on the same sub, we
1918      * don't set {@link android.telecom.Connection#EXTRA_ANSWERING_DROPS_FG_CALL} on the incoming
1919      * call extras.
1920      * @throws Exception
1921      */
1922     @Test
1923     @SmallTest
testSecondCallDifferentSubWontDisconnectForDsdaDevice()1924     public void testSecondCallDifferentSubWontDisconnectForDsdaDevice() throws Exception {
1925         // Re-uses existing test for setup, then configures device as virtual DSDA for test duration
1926         testIncomingDoesntRequestDisconnect();
1927         when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
1928 
1929         when(mCall.getState()).thenReturn(Call.State.ACTIVE);
1930         when(mCall2.getState()).thenReturn(Call.State.WAITING);
1931         when(mCall2.getLatestConnection()).thenReturn(mInternalConnection2);
1932         // At this point the call is ringing on the second phone.
1933         when(mPhone0.getRingingCall()).thenReturn(null);
1934         when(mPhone1.getRingingCall()).thenReturn(mCall2);
1935 
1936         mBinderStub.createConnection(PHONE_ACCOUNT_HANDLE_2, "TC@2",
1937                 new ConnectionRequest(PHONE_ACCOUNT_HANDLE_2, Uri.parse("tel:16505551213"),
1938                         new Bundle()),
1939                 true, false, null);
1940         waitForHandlerAction(mTestConnectionService.getHandler(), TIMEOUT_MS);
1941         assertEquals(2, mTestConnectionService.getAllConnections().size());
1942 
1943         // None of the connections should have the extra set.
1944         assertEquals(0, mTestConnectionService.getAllConnections().stream()
1945                 .filter(c -> c.getExtras() != null && c.getExtras().containsKey(
1946                         android.telecom.Connection.EXTRA_ANSWERING_DROPS_FG_CALL))
1947                 .count());
1948     }
1949 
1950     private static final PhoneAccountHandle SUB1_HANDLE = new PhoneAccountHandle(
1951             new ComponentName("test", "class"), "1");
1952     private static final PhoneAccountHandle SUB2_HANDLE = new PhoneAccountHandle(
1953             new ComponentName("test", "class"), "2");
1954 
1955     @Test
1956     @SmallTest
testDontDisconnectSameSub()1957     public void testDontDisconnectSameSub() {
1958         ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
1959         SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
1960         tcs.add(tc1);
1961         TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
1962                 tcs, SUB1_HANDLE, false, mTelephonyManagerProxy);
1963         // Would've preferred to use mockito, but can't mock out TelephonyConnection/Connection
1964         // easily.
1965         assertFalse(tc1.wasDisconnected);
1966     }
1967 
1968     @Test
1969     @SmallTest
testDontDisconnectEmergency()1970     public void testDontDisconnectEmergency() {
1971         ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
1972         SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, true);
1973         tcs.add(tc1);
1974         TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
1975                 tcs, SUB2_HANDLE, false, mTelephonyManagerProxy);
1976         // Other call is an emergency call, so don't disconnect it.
1977         assertFalse(tc1.wasDisconnected);
1978     }
1979 
1980     @Test
1981     @SmallTest
testDontDisconnectExternal()1982     public void testDontDisconnectExternal() {
1983         ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
1984         SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE,
1985                 android.telecom.Connection.PROPERTY_IS_EXTERNAL_CALL, false);
1986         tcs.add(tc1);
1987         TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
1988                 tcs, SUB2_HANDLE, false, mTelephonyManagerProxy);
1989         // Other call is an external call, so don't disconnect it.
1990         assertFalse(tc1.wasDisconnected);
1991     }
1992 
1993     @Test
1994     @SmallTest
testDisconnectDifferentSub()1995     public void testDisconnectDifferentSub() {
1996         ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
1997         SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
1998         tcs.add(tc1);
1999         TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
2000                 tcs, SUB2_HANDLE, false, mTelephonyManagerProxy);
2001         assertTrue(tc1.wasDisconnected);
2002     }
2003 
2004     @Test
2005     @SmallTest
testDisconnectDifferentSubTwoCalls()2006     public void testDisconnectDifferentSubTwoCalls() {
2007         ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
2008         SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
2009         SimpleTelephonyConnection tc2 = createTestConnection(SUB1_HANDLE, 0, false);
2010 
2011         tcs.add(tc1);
2012         tcs.add(tc2);
2013         TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
2014                 tcs, SUB2_HANDLE, false, mTelephonyManagerProxy);
2015         assertTrue(tc1.wasDisconnected);
2016         assertTrue(tc2.wasDisconnected);
2017     }
2018 
2019     /**
2020      * Verifies that DSDA or virtual DSDA-enabled devices can support active non-emergency calls on
2021      * separate subs, when the extra EXTRA_ANSWERING_DROPS_FG_CALL is not set on the incoming call.
2022      */
2023     @Test
2024     @SmallTest
testDontDisconnectDifferentSubForVirtualDsdaDevice()2025     public void testDontDisconnectDifferentSubForVirtualDsdaDevice() {
2026         when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
2027 
2028         ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
2029         SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
2030         tcs.add(tc1);
2031         TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
2032                 tcs, SUB2_HANDLE, false, mTelephonyManagerProxy);
2033         assertFalse(tc1.wasDisconnected);
2034     }
2035 
2036     /**
2037      * Verifies that DSDA or virtual DSDA-enabled devices will disconnect the existing call when the
2038      * call extra EXTRA_ANSWERING_DROPS_FG_CALL is set on the incoming call on a different sub.
2039      */
2040     @Test
2041     @SmallTest
testDisconnectDifferentSubForVirtualDsdaDevice_ifCallExtraSet()2042     public void testDisconnectDifferentSubForVirtualDsdaDevice_ifCallExtraSet() {
2043         when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
2044 
2045         ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
2046         SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
2047         tcs.add(tc1);
2048         TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
2049                 tcs, SUB2_HANDLE, true, mTelephonyManagerProxy);
2050         assertTrue(tc1.wasDisconnected);
2051     }
2052 
2053     /**
2054      * For calls on the same sub, the Dialer implements the 'swap' functionality to perform hold and
2055      * unhold, so we do not additionally unhold when 'hold' button is pressed.
2056      */
2057     @Test
2058     @SmallTest
testDontUnholdOnSameSubForVirtualDsdaDevice()2059     public void testDontUnholdOnSameSubForVirtualDsdaDevice() {
2060         when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
2061 
2062         ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
2063         Collection<Conference> conferences = new ArrayList<>();
2064         SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
2065         tcs.add(tc1);
2066         TelephonyConnectionService.maybeUnholdCallsOnOtherSubs(
2067                 tcs, conferences, SUB1_HANDLE, mTelephonyManagerProxy);
2068         assertFalse(tc1.wasUnheld);
2069     }
2070 
2071     /**
2072      * Triggering 'Hold' on 1 call will unhold the other call for DSDA or Virtual DSDA
2073      * enabled devices, effectively constituting 'swap' functionality.
2074      */
2075     @Test
2076     @SmallTest
testUnholdOnOtherSubForVirtualDsdaDevice()2077     public void testUnholdOnOtherSubForVirtualDsdaDevice() {
2078         when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
2079 
2080         ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
2081         SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
2082         tcs.add(tc1);
2083         TelephonyConnectionService.maybeUnholdCallsOnOtherSubs(
2084                 tcs, new ArrayList<>(), SUB2_HANDLE, mTelephonyManagerProxy);
2085         assertTrue(tc1.wasUnheld);
2086     }
2087 
2088     /**
2089      * Verifies hold/unhold behavior for a conference on the other sub. It does not disturb the
2090      * individual connections that participate in the conference.
2091      */
2092     @Test
2093     @SmallTest
testUnholdConferenceOnOtherSubForVirtualDsdaDevice()2094     public void testUnholdConferenceOnOtherSubForVirtualDsdaDevice() {
2095         when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
2096         SimpleTelephonyConnection tc1 =
2097                 createTestConnection(SUB1_HANDLE, 0, false);
2098         SimpleTelephonyConnection tc2 =
2099                 createTestConnection(SUB1_HANDLE, 0, false);
2100         List<android.telecom.Connection> conferenceParticipants = Arrays.asList(tc1, tc2);
2101 
2102         SimpleConference testConference = createTestConference(SUB1_HANDLE, 0);
2103         List<Conference> conferences = Arrays.asList(testConference);
2104 
2105         TelephonyConnectionService.maybeUnholdCallsOnOtherSubs(
2106                 conferenceParticipants, conferences, SUB2_HANDLE, mTelephonyManagerProxy);
2107 
2108         assertTrue(testConference.wasUnheld);
2109         assertFalse(tc1.wasUnheld);
2110         assertFalse(tc2.wasUnheld);
2111     }
2112 
2113     /**
2114      * For DSDA devices, placing an outgoing call on a 2nd sub will hold the existing ACTIVE
2115      * connection on the first sub.
2116      */
2117     @Test
2118     @SmallTest
testHoldOnOtherSubForVirtualDsdaDevice()2119     public void testHoldOnOtherSubForVirtualDsdaDevice() {
2120         when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
2121 
2122         ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
2123         SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
2124         tc1.setTelephonyConnectionActive();
2125         tcs.add(tc1);
2126 
2127         Conferenceable c = TelephonyConnectionService.maybeHoldCallsOnOtherSubs(
2128                 tcs, new ArrayList<>(), SUB2_HANDLE, mTelephonyManagerProxy);
2129         assertTrue(c.equals(tc1));
2130         assertTrue(tc1.wasHeld);
2131     }
2132 
2133     /**
2134      * For DSDA devices with AP domain selection service enabled, placing an outgoing call
2135      * on a 2nd sub will hold the existing ACTIVE connection on the first sub.
2136      */
2137     @Test
2138     @SmallTest
testHoldOnOtherSubForVirtualDsdaDeviceWithDomainSelectionEnabled()2139     public void testHoldOnOtherSubForVirtualDsdaDeviceWithDomainSelectionEnabled() {
2140         when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
2141         doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
2142 
2143         ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
2144         SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
2145         tc1.setTelephonyConnectionActive();
2146         tcs.add(tc1);
2147 
2148         Conferenceable c = TelephonyConnectionService.maybeHoldCallsOnOtherSubs(
2149                 tcs, new ArrayList<>(), SUB2_HANDLE, mTelephonyManagerProxy);
2150         assertTrue(c.equals(tc1));
2151         assertTrue(tc1.wasHeld);
2152     }
2153 
2154     /**
2155      * For DSDA devices, if the existing connection was already held, placing an outgoing call on a
2156      * 2nd sub will not attempt to hold the existing connection on the first sub.
2157      */
2158     @Test
2159     @SmallTest
testNoHold_ifExistingConnectionAlreadyHeld_ForVirtualDsdaDevice()2160     public void testNoHold_ifExistingConnectionAlreadyHeld_ForVirtualDsdaDevice() {
2161         when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
2162 
2163         ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
2164         SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
2165         tc1.setTelephonyConnectionOnHold();
2166         tcs.add(tc1);
2167 
2168         Conferenceable c = TelephonyConnectionService.maybeHoldCallsOnOtherSubs(
2169                 tcs, new ArrayList<>(), SUB2_HANDLE, mTelephonyManagerProxy);
2170         assertNull(c);
2171     }
2172 
2173     // For 'Virtual DSDA' devices, if there is an existing call on sub1, an outgoing call on sub2
2174     // will place the sub1 call on hold.
2175     @Test
2176     @SmallTest
testOutgoingCallOnOtherSubPutsFirstCallOnHoldForVirtualDsdaDevice()2177     public void testOutgoingCallOnOtherSubPutsFirstCallOnHoldForVirtualDsdaDevice()
2178             throws Exception {
2179         setupForCallTest();
2180         when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
2181         doNothing().when(mContext).startActivityAsUser(any(), any());
2182 
2183         mBinderStub.createConnection(PHONE_ACCOUNT_HANDLE_1, "TC@1",
2184                 new ConnectionRequest(PHONE_ACCOUNT_HANDLE_1, Uri.parse("tel:16505551212"),
2185                         new Bundle()),
2186                 true, false, null);
2187         waitForHandlerAction(mTestConnectionService.getHandler(), TIMEOUT_MS);
2188         assertEquals(1, mTestConnectionService.getAllConnections().size());
2189 
2190         TelephonyConnection connection1 = (TelephonyConnection)
2191                 mTestConnectionService.getAllConnections().toArray()[0];
2192 
2193         TelephonyConnection connection2 = (TelephonyConnection) mTestConnectionService
2194                 .onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_2,
2195                         createConnectionRequest(PHONE_ACCOUNT_HANDLE_2, "1234", "TC@2"));
2196         assertNotNull("test connection was not set up correctly.", connection2);
2197 
2198         // Simulates that connection1 is placed on HOLD.
2199         connection1.setTelephonyConnectionOnHold();
2200 
2201         verify(mPhone1).dial(anyString(), any(), any());
2202         assertEquals(connection1.getState(), android.telecom.Connection.STATE_HOLDING);
2203     }
2204 
2205     // For 'Virtual DSDA' devices, if the carrier config 'KEY_ALLOW_HOLD_CALL_DURING_EMERGENCY_BOOL'
2206     // is not configured, or set to true, an outgoing emergency call will place the existing call on
2207     // a different sub on hold.
2208     @Test
2209     @SmallTest
testEmergencyCallOnOtherSubPutsFirstCallOnHoldForVirtualDsdaDevice()2210     public void testEmergencyCallOnOtherSubPutsFirstCallOnHoldForVirtualDsdaDevice()
2211             throws Exception {
2212         setupForCallTest();
2213         when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
2214         doNothing().when(mContext).startActivityAsUser(any(), any());
2215 
2216         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
2217         mBinderStub.createConnection(PHONE_ACCOUNT_HANDLE_1, "TC@1",
2218                 new ConnectionRequest(PHONE_ACCOUNT_HANDLE_1, Uri.parse("tel:16505551212"),
2219                         new Bundle()),
2220                 true, false, null);
2221         waitForHandlerAction(mTestConnectionService.getHandler(), TIMEOUT_MS);
2222         assertEquals(1, mTestConnectionService.getAllConnections().size());
2223 
2224         TelephonyConnection connection1 = (TelephonyConnection)
2225                 mTestConnectionService.getAllConnections().toArray()[0];
2226 
2227         // Simulates an outgoing emergency call.
2228         TelephonyConnection connection2 = (TelephonyConnection) mTestConnectionService
2229                 .onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_2,
2230                         createConnectionRequest(PHONE_ACCOUNT_HANDLE_2,
2231                                 TEST_EMERGENCY_NUMBER, "TC@2"));
2232         assertNotNull("test connection was not set up correctly.", connection2);
2233 
2234         // Simulates that connection1 is placed on HOLD.
2235         connection1.setTelephonyConnectionOnHold();
2236 
2237         verify(mPhone1).dial(anyString(), any(), any());
2238         assertEquals(connection1.getState(), android.telecom.Connection.STATE_HOLDING);
2239     }
2240 
2241     // For 'Virtual DSDA' devices If the carrier config 'KEY_ALLOW_HOLD_CALL_DURING_EMERGENCY_BOOL'
2242     // is explicitly configured false, an outgoing emergency call will disconnect all existing
2243     // calls, across subscriptions.
2244     @Test
2245     @SmallTest
testEmergencyCallOnOtherSubDisconnectsExistingCallForVirtualDsdaDevice()2246     public void testEmergencyCallOnOtherSubDisconnectsExistingCallForVirtualDsdaDevice()
2247             throws Exception {
2248         setupForCallTest();
2249         when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
2250         doNothing().when(mContext).startActivityAsUser(any(), any());
2251 
2252         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
2253         getTestContext().getCarrierConfig(0 /*subId*/).putBoolean(
2254                 CarrierConfigManager.KEY_ALLOW_HOLD_CALL_DURING_EMERGENCY_BOOL, false);
2255 
2256         mBinderStub.createConnection(PHONE_ACCOUNT_HANDLE_1, "TC@1",
2257                 new ConnectionRequest(PHONE_ACCOUNT_HANDLE_1, Uri.parse("tel:16505551212"),
2258                         new Bundle()),
2259                 true, false, null);
2260         waitForHandlerAction(mTestConnectionService.getHandler(), TIMEOUT_MS);
2261         assertEquals(1, mTestConnectionService.getAllConnections().size());
2262 
2263         TelephonyConnection connection1 = (TelephonyConnection)
2264                 mTestConnectionService.getAllConnections().toArray()[0];
2265 
2266         // Simulates an outgoing emergency call.
2267         TelephonyConnection connection2 = (TelephonyConnection) mTestConnectionService
2268                 .onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_2,
2269                         createConnectionRequest(PHONE_ACCOUNT_HANDLE_2,
2270                                 TEST_EMERGENCY_NUMBER, "TC@2"));
2271         assertNotNull("test connection was not set up correctly.", connection2);
2272 
2273         verify(mPhone1).dial(anyString(), any(), any());
2274         assertEquals(connection1.getState(), android.telecom.Connection.STATE_DISCONNECTED);
2275     }
2276 
2277     /**
2278      * Verifies that TelephonyManager is used to determine whether a connection is Emergency when
2279      * creating an outgoing connection.
2280      */
2281     @Test
2282     @SmallTest
testIsEmergencyDeterminedByTelephonyManager()2283     public void testIsEmergencyDeterminedByTelephonyManager() {
2284         ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
2285                 .setAccountHandle(PHONE_ACCOUNT_HANDLE_1)
2286                 .setAddress(TEST_ADDRESS)
2287                 .build();
2288         mConnection = mTestConnectionService.onCreateOutgoingConnection(
2289                 PHONE_ACCOUNT_HANDLE_1, connectionRequest);
2290 
2291         verify(mTelephonyManagerProxy)
2292                 .isCurrentEmergencyNumber(TEST_ADDRESS.getSchemeSpecificPart());
2293     }
2294 
2295     @Test
testDomainSelectionCs()2296     public void testDomainSelectionCs() throws Exception {
2297         setupForCallTest();
2298 
2299         int selectedDomain = DOMAIN_CS;
2300 
2301         setupForDialForDomainSelection(mPhone0, selectedDomain, true);
2302 
2303         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
2304                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
2305                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
2306 
2307         ArgumentCaptor<android.telecom.Connection> connectionCaptor =
2308                 ArgumentCaptor.forClass(android.telecom.Connection.class);
2309 
2310         verify(mDomainSelectionResolver)
2311                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
2312         verify(mEmergencyStateTracker)
2313                 .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
2314         verify(mSatelliteSOSMessageRecommender, times(2)).onEmergencyCallStarted(any(),
2315                 anyBoolean());
2316         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
2317 
2318         android.telecom.Connection tc = connectionCaptor.getValue();
2319 
2320         assertNotNull(tc);
2321         assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
2322         assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
2323 
2324         ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
2325 
2326         verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
2327         DialArgs dialArgs = argsCaptor.getValue();
2328         assertNotNull("DialArgs param is null", dialArgs);
2329         assertNotNull("intentExtras is null", dialArgs.intentExtras);
2330         assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
2331         assertEquals(selectedDomain,
2332                 dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
2333     }
2334 
2335     @Test
testDomainSelectionPs()2336     public void testDomainSelectionPs() throws Exception {
2337         setupForCallTest();
2338 
2339         int selectedDomain = DOMAIN_PS;
2340 
2341         setupForDialForDomainSelection(mPhone0, selectedDomain, true);
2342 
2343         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
2344                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
2345                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
2346 
2347         ArgumentCaptor<android.telecom.Connection> connectionCaptor =
2348                 ArgumentCaptor.forClass(android.telecom.Connection.class);
2349 
2350         verify(mDomainSelectionResolver)
2351                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
2352         verify(mEmergencyStateTracker)
2353                 .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
2354         verify(mSatelliteSOSMessageRecommender, times(2)).onEmergencyCallStarted(any(),
2355                 anyBoolean());
2356         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
2357 
2358         android.telecom.Connection tc = connectionCaptor.getValue();
2359 
2360         assertNotNull(tc);
2361         assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
2362         assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
2363 
2364         ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
2365 
2366         verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
2367         DialArgs dialArgs = argsCaptor.getValue();
2368         assertNotNull("DialArgs param is null", dialArgs);
2369         assertNotNull("intentExtras is null", dialArgs.intentExtras);
2370         assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
2371         assertEquals(selectedDomain,
2372                 dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
2373     }
2374 
2375     @Test
testDomainSelectionCsForTty()2376     public void testDomainSelectionCsForTty() throws Exception {
2377         setupForCallTest();
2378 
2379         ImsManager imsManager = Mockito.mock(ImsManager.class);
2380         doReturn(false).when(imsManager).isNonTtyOrTtyOnVolteEnabled();
2381         replaceInstance(TelephonyConnectionService.class,
2382                 "mImsManager", mTestConnectionService, imsManager);
2383 
2384         int selectedDomain = DOMAIN_PS;
2385 
2386         setupForDialForDomainSelection(mPhone0, selectedDomain, true);
2387 
2388         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
2389                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
2390                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
2391 
2392         ArgumentCaptor<android.telecom.Connection> connectionCaptor =
2393                 ArgumentCaptor.forClass(android.telecom.Connection.class);
2394 
2395         verify(mDomainSelectionResolver)
2396                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
2397         verify(mEmergencyStateTracker)
2398                 .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
2399         verify(mSatelliteSOSMessageRecommender, times(2)).onEmergencyCallStarted(any(),
2400                 anyBoolean());
2401         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
2402 
2403         android.telecom.Connection tc = connectionCaptor.getValue();
2404 
2405         assertNotNull(tc);
2406         assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
2407         assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
2408 
2409         ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
2410 
2411         verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
2412         DialArgs dialArgs = argsCaptor.getValue();
2413         assertNotNull("DialArgs param is null", dialArgs);
2414         assertNotNull("intentExtras is null", dialArgs.intentExtras);
2415         assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
2416         assertEquals(selectedDomain,
2417                 dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
2418     }
2419 
2420     @Test
testDomainSelectionRedialCs()2421     public void testDomainSelectionRedialCs() throws Exception {
2422         setupForCallTest();
2423 
2424         int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
2425         int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
2426         int selectedDomain = DOMAIN_CS;
2427 
2428         TestTelephonyConnection c = setupForReDialForDomainSelection(
2429                 mPhone0, selectedDomain, preciseDisconnectCause, disconnectCause, true);
2430 
2431         assertTrue(mTestConnectionService.maybeReselectDomain(c, null, true,
2432                 android.telephony.DisconnectCause.NOT_VALID));
2433         verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
2434         verify(mEmergencyCallDomainSelectionConnection).setDisconnectCause(
2435                 eq(disconnectCause), eq(preciseDisconnectCause), any());
2436 
2437         ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
2438 
2439         doReturn(mInternalConnection).when(mPhone0).dial(anyString(), any(), any());
2440 
2441         verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
2442         DialArgs dialArgs = argsCaptor.getValue();
2443         assertNotNull("DialArgs param is null", dialArgs);
2444         assertNotNull("intentExtras is null", dialArgs.intentExtras);
2445         assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
2446         assertEquals(selectedDomain,
2447                 dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
2448     }
2449 
2450     @Test
testDomainSelectionRedialPs()2451     public void testDomainSelectionRedialPs() throws Exception {
2452         setupForCallTest();
2453 
2454         int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
2455         int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
2456         int selectedDomain = DOMAIN_PS;
2457 
2458         TestTelephonyConnection c = setupForReDialForDomainSelection(
2459                 mPhone0, selectedDomain, preciseDisconnectCause, disconnectCause, true);
2460 
2461         assertTrue(mTestConnectionService.maybeReselectDomain(c, null, false,
2462                 android.telephony.DisconnectCause.ICC_ERROR));
2463         verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
2464         verify(mEmergencyCallDomainSelectionConnection).setDisconnectCause(
2465                 eq(android.telephony.DisconnectCause.ICC_ERROR),
2466                 eq(com.android.internal.telephony.CallFailCause.NOT_VALID),
2467                 any());
2468 
2469         ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
2470 
2471         doReturn(mInternalConnection).when(mPhone0).dial(anyString(), any(), any());
2472 
2473         verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
2474         DialArgs dialArgs = argsCaptor.getValue();
2475         assertNotNull("DialArgs param is null", dialArgs);
2476         assertNotNull("intentExtras is null", dialArgs.intentExtras);
2477         assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
2478         assertEquals(selectedDomain,
2479                 dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
2480     }
2481 
2482     @Test
testDomainSelectionRedialFailedWithException()2483     public void testDomainSelectionRedialFailedWithException() throws Exception {
2484         setupForCallTest();
2485 
2486         int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
2487         int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
2488         int selectedDomain = DOMAIN_CS;
2489 
2490         TestTelephonyConnection c = setupForReDialForDomainSelection(
2491                 mPhone0, selectedDomain, preciseDisconnectCause, disconnectCause, true);
2492 
2493         CallStateException cse = new CallStateException(CallStateException.ERROR_CALLING_DISABLED,
2494                 "Calling disabled via ro.telephony.disable-call property");
2495         doThrow(cse).when(mPhone0).dial(anyString(), any(), any());
2496 
2497         assertTrue(mTestConnectionService.maybeReselectDomain(c, null, true,
2498                 android.telephony.DisconnectCause.NOT_VALID));
2499         verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
2500         verify(mEmergencyCallDomainSelectionConnection).cancelSelection();
2501         verify(mEmergencyStateTracker).endCall(any());
2502     }
2503 
2504     @Test
testDomainSelectionRejectIncoming()2505     public void testDomainSelectionRejectIncoming() throws Exception {
2506         setupForCallTest();
2507 
2508         int selectedDomain = DOMAIN_CS;
2509 
2510         setupForDialForDomainSelection(mPhone0, selectedDomain, true);
2511 
2512         doReturn(mInternalConnection2).when(mCall).getLatestConnection();
2513         doReturn(Call.State.INCOMING).when(mCall).getState();
2514         doReturn(mCall).when(mPhone0).getRingingCall();
2515 
2516         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
2517                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
2518                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
2519 
2520         ArgumentCaptor<android.telecom.Connection> connectionCaptor =
2521                 ArgumentCaptor.forClass(android.telecom.Connection.class);
2522 
2523         verify(mDomainSelectionResolver)
2524                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
2525         verify(mEmergencyStateTracker)
2526                 .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
2527         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
2528 
2529         android.telecom.Connection tc = connectionCaptor.getValue();
2530 
2531         assertNotNull(tc);
2532         assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
2533         assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
2534 
2535         ArgumentCaptor<Connection.Listener> listenerCaptor =
2536                 ArgumentCaptor.forClass(Connection.Listener.class);
2537 
2538         verify(mInternalConnection2).addListener(listenerCaptor.capture());
2539         verify(mCall).hangup();
2540         verify(mPhone0, never()).dial(anyString(), any(), any());
2541 
2542         Connection.Listener listener = listenerCaptor.getValue();
2543 
2544         assertNotNull(listener);
2545 
2546         listener.onDisconnect(0);
2547 
2548         verify(mSatelliteSOSMessageRecommender, times(2)).onEmergencyCallStarted(any(),
2549                 anyBoolean());
2550 
2551         ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
2552 
2553         verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
2554 
2555         DialArgs dialArgs = argsCaptor.getValue();
2556 
2557         assertNotNull("DialArgs param is null", dialArgs);
2558         assertNotNull("intentExtras is null", dialArgs.intentExtras);
2559         assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
2560         assertEquals(selectedDomain,
2561                 dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
2562     }
2563 
2564     @Test
testDomainSelectionRedialRejectIncoming()2565     public void testDomainSelectionRedialRejectIncoming() throws Exception {
2566         setupForCallTest();
2567 
2568         int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
2569         int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
2570         int selectedDomain = DOMAIN_CS;
2571 
2572         TestTelephonyConnection c = setupForReDialForDomainSelection(
2573                 mPhone0, selectedDomain, preciseDisconnectCause, disconnectCause, true);
2574 
2575         doReturn(mInternalConnection2).when(mCall).getLatestConnection();
2576         doReturn(Call.State.DISCONNECTING).when(mCall).getState();
2577         doReturn(mCall).when(mPhone0).getRingingCall();
2578 
2579         assertTrue(mTestConnectionService.maybeReselectDomain(c, null, true,
2580                 android.telephony.DisconnectCause.NOT_VALID));
2581         verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
2582 
2583         ArgumentCaptor<Connection.Listener> listenerCaptor =
2584                 ArgumentCaptor.forClass(Connection.Listener.class);
2585 
2586         verify(mInternalConnection2).addListener(listenerCaptor.capture());
2587         verify(mCall).hangup();
2588         verify(mPhone0, never()).dial(anyString(), any(), any());
2589 
2590         Connection.Listener listener = listenerCaptor.getValue();
2591 
2592         assertNotNull(listener);
2593 
2594         listener.onDisconnect(0);
2595 
2596         ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
2597 
2598         verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
2599         DialArgs dialArgs = argsCaptor.getValue();
2600         assertNotNull("DialArgs param is null", dialArgs);
2601         assertNotNull("intentExtras is null", dialArgs.intentExtras);
2602         assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
2603         assertEquals(selectedDomain,
2604                 dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
2605     }
2606 
2607     @Test
testDomainSelectionNormalRoutingEmergencyNumber()2608     public void testDomainSelectionNormalRoutingEmergencyNumber() throws Exception {
2609         setupForCallTest();
2610         int selectedDomain = DOMAIN_PS;
2611 
2612         EmergencyNumber emergencyNumber = new EmergencyNumber(TEST_EMERGENCY_NUMBER, "", "",
2613                 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
2614                 Collections.emptyList(),
2615                 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE,
2616                 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
2617 
2618         setupForDialForDomainSelection(mPhone0, selectedDomain, false);
2619         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
2620         doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
2621         doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
2622                 anyString());
2623 
2624         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
2625                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
2626                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
2627 
2628         ArgumentCaptor<TelephonyConnection> connectionCaptor =
2629                 ArgumentCaptor.forClass(TelephonyConnection.class);
2630         ArgumentCaptor<Consumer<Boolean>> consumerCaptor = ArgumentCaptor
2631                 .forClass(Consumer.class);
2632 
2633         verify(mEmergencyStateTracker).startNormalRoutingEmergencyCall(eq(mPhone0),
2634                 connectionCaptor.capture(), consumerCaptor.capture());
2635 
2636         TelephonyConnection tc = connectionCaptor.getValue();
2637 
2638         assertNotNull(tc);
2639         assertNotNull(mTestConnectionService.getNormalRoutingEmergencyConnection());
2640         assertEquals(mTestConnectionService.getNormalRoutingEmergencyConnection(), tc);
2641 
2642         verify(mDomainSelectionResolver, never())
2643                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(false));
2644         verify(mNormalCallDomainSelectionConnection, never()).createNormalConnection(any(), any());
2645 
2646         Consumer<Boolean> consumer = consumerCaptor.getValue();
2647 
2648         assertNotNull(consumer);
2649 
2650         consumer.accept(true);
2651 
2652         verify(mDomainSelectionResolver)
2653                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(false));
2654         verify(mNormalCallDomainSelectionConnection).createNormalConnection(any(), any());
2655         verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), anyBoolean());
2656 
2657         ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
2658 
2659         verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
2660         DialArgs dialArgs = argsCaptor.getValue();
2661         assertNotNull("DialArgs param is null", dialArgs);
2662         assertNotNull("intentExtras is null", dialArgs.intentExtras);
2663         assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
2664         assertEquals(
2665                 selectedDomain, dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
2666     }
2667 
2668     @Test
testDomainSelectionNormalRoutingEmergencyNumberAndDiscarded()2669     public void testDomainSelectionNormalRoutingEmergencyNumberAndDiscarded() throws Exception {
2670         setupForCallTest();
2671         int selectedDomain = DOMAIN_PS;
2672 
2673         EmergencyNumber emergencyNumber = new EmergencyNumber(TEST_EMERGENCY_NUMBER, "", "",
2674                 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
2675                 Collections.emptyList(),
2676                 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE,
2677                 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
2678 
2679         setupForDialForDomainSelection(mPhone0, selectedDomain, false);
2680         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
2681         doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
2682         doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
2683                 anyString());
2684 
2685         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
2686                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
2687                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
2688 
2689         ArgumentCaptor<TelephonyConnection> connectionCaptor =
2690                 ArgumentCaptor.forClass(TelephonyConnection.class);
2691         ArgumentCaptor<Consumer<Boolean>> consumerCaptor = ArgumentCaptor
2692                 .forClass(Consumer.class);
2693 
2694         verify(mEmergencyStateTracker).startNormalRoutingEmergencyCall(eq(mPhone0),
2695                 connectionCaptor.capture(), consumerCaptor.capture());
2696 
2697         TelephonyConnection tc = connectionCaptor.getValue();
2698 
2699         assertNotNull(tc);
2700         assertNotNull(mTestConnectionService.getNormalRoutingEmergencyConnection());
2701         assertEquals(mTestConnectionService.getNormalRoutingEmergencyConnection(), tc);
2702 
2703         verify(mDomainSelectionResolver, never())
2704                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(false));
2705         verify(mNormalCallDomainSelectionConnection, never()).createNormalConnection(any(), any());
2706 
2707         Consumer<Boolean> consumer = consumerCaptor.getValue();
2708 
2709         assertNotNull(consumer);
2710 
2711         // Discard dialing
2712         tc.hangup(android.telephony.DisconnectCause.LOCAL);
2713 
2714         consumer.accept(true);
2715 
2716         verify(mDomainSelectionResolver, never())
2717                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(false));
2718         verify(mNormalCallDomainSelectionConnection, never()).createNormalConnection(any(), any());
2719     }
2720 
2721     @Test
testDomainSelectionDialedSimEmergencyNumberOnlyFalse()2722     public void testDomainSelectionDialedSimEmergencyNumberOnlyFalse() throws Exception {
2723         setupForCallTest();
2724 
2725         int selectedDomain = DOMAIN_PS;
2726 
2727         EmergencyNumber emergencyNumber = new EmergencyNumber(TEST_EMERGENCY_NUMBER, "", "",
2728                 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
2729                 Collections.emptyList(),
2730                 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE,
2731                 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY);
2732 
2733         setupForDialForDomainSelection(mPhone0, selectedDomain, true);
2734         doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
2735         doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
2736                 anyString());
2737         doReturn(false).when(mEmergencyNumberTracker).isEmergencyNumber(anyString());
2738         getTestContext().getCarrierConfig(0 /*subId*/).putBoolean(
2739                 CarrierConfigManager.KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL, false);
2740 
2741         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
2742                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
2743                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
2744 
2745         ArgumentCaptor<android.telecom.Connection> connectionCaptor =
2746                 ArgumentCaptor.forClass(android.telecom.Connection.class);
2747 
2748         verify(mDomainSelectionResolver)
2749                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
2750         verify(mEmergencyStateTracker)
2751                 .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
2752         verify(mSatelliteSOSMessageRecommender, times(2)).onEmergencyCallStarted(any(),
2753                 anyBoolean());
2754         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
2755 
2756         android.telecom.Connection tc = connectionCaptor.getValue();
2757 
2758         assertNotNull(tc);
2759         assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
2760         assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
2761 
2762         ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
2763 
2764         verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
2765         DialArgs dialArgs = argsCaptor.getValue();
2766         assertNotNull("DialArgs param is null", dialArgs);
2767         assertNotNull("intentExtras is null", dialArgs.intentExtras);
2768         assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
2769         assertEquals(selectedDomain,
2770                 dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
2771     }
2772 
2773     @Test
testDomainSelectionDialedSimEmergencyNumberOnlyTrue()2774     public void testDomainSelectionDialedSimEmergencyNumberOnlyTrue() throws Exception {
2775         setupForCallTest();
2776         int selectedDomain = DOMAIN_PS;
2777 
2778         EmergencyNumber emergencyNumber = new EmergencyNumber(TEST_EMERGENCY_NUMBER, "", "",
2779                 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
2780                 Collections.emptyList(),
2781                 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE,
2782                 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY);
2783 
2784         setupForDialForDomainSelection(mPhone0, selectedDomain, false);
2785         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
2786         doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
2787         doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
2788                 anyString());
2789         doReturn(false).when(mEmergencyNumberTracker).isEmergencyNumber(anyString());
2790         getTestContext().getCarrierConfig(0 /*subId*/).putBoolean(
2791                 CarrierConfigManager.KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL, true);
2792 
2793         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
2794                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
2795                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
2796 
2797         ArgumentCaptor<TelephonyConnection> connectionCaptor =
2798                 ArgumentCaptor.forClass(TelephonyConnection.class);
2799         ArgumentCaptor<Consumer<Boolean>> consumerCaptor = ArgumentCaptor
2800                 .forClass(Consumer.class);
2801 
2802         verify(mEmergencyStateTracker).startNormalRoutingEmergencyCall(eq(mPhone0),
2803                 connectionCaptor.capture(), consumerCaptor.capture());
2804 
2805         TelephonyConnection tc = connectionCaptor.getValue();
2806 
2807         assertNotNull(tc);
2808         assertNotNull(mTestConnectionService.getNormalRoutingEmergencyConnection());
2809         assertEquals(mTestConnectionService.getNormalRoutingEmergencyConnection(), tc);
2810 
2811         verify(mDomainSelectionResolver, never())
2812                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(false));
2813         verify(mNormalCallDomainSelectionConnection, never()).createNormalConnection(any(), any());
2814 
2815         Consumer<Boolean> consumer = consumerCaptor.getValue();
2816 
2817         assertNotNull(consumer);
2818 
2819         consumer.accept(true);
2820 
2821         verify(mDomainSelectionResolver)
2822                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(false));
2823         verify(mNormalCallDomainSelectionConnection).createNormalConnection(any(), any());
2824         verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), anyBoolean());
2825 
2826         ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
2827 
2828         verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
2829         DialArgs dialArgs = argsCaptor.getValue();
2830         assertNotNull("DialArgs param is null", dialArgs);
2831         assertNotNull("intentExtras is null", dialArgs.intentExtras);
2832         assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
2833         assertEquals(
2834                 selectedDomain, dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
2835     }
2836 
2837     @Test
testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_InService()2838     public void testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_InService()
2839             throws Exception {
2840         when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
2841         Phone testPhone = setupConnectionServiceInApmForDomainSelection(true);
2842 
2843         ArgumentCaptor<RadioOnStateListener.Callback> callback =
2844                 ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
2845         verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
2846                 eq(testPhone), eq(false), eq(TIMEOUT_TO_DYNAMIC_ROUTING_MS));
2847 
2848         ServiceState ss = new ServiceState();
2849         ss.setState(ServiceState.STATE_OUT_OF_SERVICE);
2850         when(testPhone.getServiceState()).thenReturn(ss);
2851         when(mSST.getServiceState()).thenReturn(ss);
2852 
2853         assertFalse(callback.getValue()
2854                 .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
2855 
2856         when(mSST.isRadioOn()).thenReturn(true);
2857 
2858         assertFalse(callback.getValue()
2859                 .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
2860 
2861         Phone otherPhone = makeTestPhone(1, ServiceState.STATE_OUT_OF_SERVICE, false);
2862         when(otherPhone.getServiceState()).thenReturn(ss);
2863 
2864         // Radio on is OK for other phone
2865         assertTrue(callback.getValue()
2866                 .isOkToCall(otherPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
2867 
2868         ss.setState(ServiceState.STATE_IN_SERVICE);
2869 
2870         assertTrue(callback.getValue()
2871                 .isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, false));
2872 
2873         mConnection.setDisconnected(null);
2874     }
2875 
2876     @Test
testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_Timeout()2877     public void testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_Timeout()
2878             throws Exception {
2879         when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
2880         Phone testPhone = setupConnectionServiceInApmForDomainSelection(true);
2881 
2882         ArgumentCaptor<RadioOnStateListener.Callback> callback =
2883                 ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
2884         verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
2885                 eq(testPhone), eq(false), eq(TIMEOUT_TO_DYNAMIC_ROUTING_MS));
2886 
2887         ServiceState ss = new ServiceState();
2888         ss.setState(ServiceState.STATE_OUT_OF_SERVICE);
2889         when(testPhone.getServiceState()).thenReturn(ss);
2890         when(mSST.getServiceState()).thenReturn(ss);
2891         when(mSST.isRadioOn()).thenReturn(true);
2892 
2893         assertFalse(callback.getValue()
2894                 .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
2895         assertTrue(callback.getValue()
2896                 .onTimeout(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
2897 
2898         mConnection.setDisconnected(null);
2899     }
2900 
2901     @Test
testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_CombinedAttach()2902     public void testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_CombinedAttach()
2903             throws Exception {
2904         when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
2905         Phone testPhone = setupConnectionServiceInApmForDomainSelection(true);
2906 
2907         ArgumentCaptor<RadioOnStateListener.Callback> callback =
2908                 ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
2909         verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
2910                 eq(testPhone), eq(false), eq(TIMEOUT_TO_DYNAMIC_ROUTING_MS));
2911 
2912         ServiceState ss = new ServiceState();
2913         ss.setState(ServiceState.STATE_IN_SERVICE);
2914         when(testPhone.getServiceState()).thenReturn(ss);
2915         when(mSST.getServiceState()).thenReturn(ss);
2916         when(mSST.isRadioOn()).thenReturn(true);
2917 
2918         DataSpecificRegistrationInfo dsri = new DataSpecificRegistrationInfo.Builder(3)
2919                 .setLteAttachResultType(DataSpecificRegistrationInfo.LTE_ATTACH_TYPE_COMBINED)
2920                 .build();
2921 
2922         NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
2923                 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
2924                 .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
2925                 .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
2926                 .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
2927                 .setDataSpecificInfo(dsri)
2928                 .build();
2929         ss.addNetworkRegistrationInfo(nri);
2930 
2931         assertTrue(callback.getValue()
2932                 .isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, false));
2933 
2934         mConnection.setDisconnected(null);
2935     }
2936 
2937     @Test
testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_PsOnly()2938     public void testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_PsOnly()
2939             throws Exception {
2940         when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
2941         Phone testPhone = setupConnectionServiceInApmForDomainSelection(true);
2942 
2943         ArgumentCaptor<RadioOnStateListener.Callback> callback =
2944                 ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
2945         verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
2946                 eq(testPhone), eq(false), eq(TIMEOUT_TO_DYNAMIC_ROUTING_MS));
2947 
2948         ServiceState ss = new ServiceState();
2949         ss.setState(ServiceState.STATE_IN_SERVICE);
2950         when(testPhone.getServiceState()).thenReturn(ss);
2951         when(mSST.getServiceState()).thenReturn(ss);
2952         when(mSST.isRadioOn()).thenReturn(true);
2953 
2954         DataSpecificRegistrationInfo dsri = new DataSpecificRegistrationInfo.Builder(3)
2955                 .build();
2956 
2957         NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
2958                 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
2959                 .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
2960                 .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
2961                 .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
2962                 .setDataSpecificInfo(dsri)
2963                 .build();
2964         ss.addNetworkRegistrationInfo(nri);
2965 
2966         assertFalse(callback.getValue()
2967                 .isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, false));
2968         assertTrue(callback.getValue()
2969                 .onTimeout(testPhone, ServiceState.STATE_IN_SERVICE, false));
2970 
2971         mConnection.setDisconnected(null);
2972     }
2973 
2974     @Test
testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_PsOnly_ImsRegistered()2975     public void testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_PsOnly_ImsRegistered()
2976             throws Exception {
2977         when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
2978         Phone testPhone = setupConnectionServiceInApmForDomainSelection(true);
2979 
2980         ArgumentCaptor<RadioOnStateListener.Callback> callback =
2981                 ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
2982         verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
2983                 eq(testPhone), eq(false), eq(TIMEOUT_TO_DYNAMIC_ROUTING_MS));
2984 
2985         ServiceState ss = new ServiceState();
2986         ss.setState(ServiceState.STATE_IN_SERVICE);
2987         when(testPhone.getServiceState()).thenReturn(ss);
2988         when(mSST.getServiceState()).thenReturn(ss);
2989         when(mSST.isRadioOn()).thenReturn(true);
2990 
2991         DataSpecificRegistrationInfo dsri = new DataSpecificRegistrationInfo.Builder(3)
2992                 .build();
2993 
2994         NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
2995                 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
2996                 .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
2997                 .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
2998                 .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
2999                 .setDataSpecificInfo(dsri)
3000                 .build();
3001         ss.addNetworkRegistrationInfo(nri);
3002 
3003         assertFalse(callback.getValue()
3004                 .isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, false));
3005         assertTrue(callback.getValue()
3006                 .isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, true));
3007 
3008         mConnection.setDisconnected(null);
3009     }
3010 
3011     @Test
testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_DiscardDialing()3012     public void testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_DiscardDialing()
3013             throws Exception {
3014         when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
3015         Phone testPhone = setupConnectionServiceInApmForDomainSelection(true);
3016 
3017         ArgumentCaptor<RadioOnStateListener.Callback> callback =
3018                 ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
3019         verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
3020                 eq(testPhone), eq(false), eq(TIMEOUT_TO_DYNAMIC_ROUTING_MS));
3021 
3022         mConnection.setDisconnected(null);
3023 
3024         assertTrue(callback.getValue()
3025                 .isOkToCall(testPhone, ServiceState.STATE_POWER_OFF, false));
3026     }
3027 
3028     @Test
testDomainSelectionNormalToEmergencyCs()3029     public void testDomainSelectionNormalToEmergencyCs() throws Exception {
3030         setupForCallTest();
3031 
3032         int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
3033         int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
3034         int eccCategory = EMERGENCY_SERVICE_CATEGORY_POLICE;
3035         int selectedDomain = DOMAIN_CS;
3036 
3037         setupForDialForDomainSelection(mPhone0, selectedDomain, true);
3038         doReturn(mPhone0).when(mImsPhone).getDefaultPhone();
3039         doReturn(mInternalConnection).when(mPhone0).dial(anyString(), any(), any());
3040 
3041         TestTelephonyConnection c = setupForReDialForDomainSelection(
3042                 mImsPhone, selectedDomain, preciseDisconnectCause, disconnectCause, false);
3043         c.setEmergencyServiceCategory(eccCategory);
3044         c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
3045 
3046         ImsReasonInfo reasonInfo = new ImsReasonInfo(CODE_SIP_ALTERNATE_EMERGENCY_CALL, 0, null);
3047         assertTrue(mTestConnectionService.maybeReselectDomain(c, reasonInfo, true,
3048                 android.telephony.DisconnectCause.NOT_VALID));
3049 
3050         ArgumentCaptor<android.telecom.Connection> connectionCaptor =
3051                 ArgumentCaptor.forClass(android.telecom.Connection.class);
3052 
3053         verify(mDomainSelectionResolver)
3054                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
3055         verify(mEmergencyStateTracker)
3056                 .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
3057         verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), anyBoolean());
3058         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
3059 
3060         android.telecom.Connection tc = connectionCaptor.getValue();
3061 
3062         assertNotNull(tc);
3063         assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
3064         assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
3065 
3066         ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
3067 
3068         verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
3069         DialArgs dialArgs = argsCaptor.getValue();
3070         assertNotNull("DialArgs param is null", dialArgs);
3071         assertNotNull("intentExtras is null", dialArgs.intentExtras);
3072         assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
3073         assertEquals(selectedDomain,
3074                 dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
3075         assertTrue(dialArgs.isEmergency);
3076         assertEquals(eccCategory, dialArgs.eccCategory);
3077         assertTrue(dialArgs.intentExtras.getBoolean(
3078                 PhoneConstants.EXTRA_USE_EMERGENCY_ROUTING, false));
3079     }
3080 
3081     @Test
testDomainSelectionNormalToEmergencyPs()3082     public void testDomainSelectionNormalToEmergencyPs() throws Exception {
3083         setupForCallTest();
3084 
3085         int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
3086         int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
3087         int eccCategory = EMERGENCY_SERVICE_CATEGORY_POLICE;
3088         int selectedDomain = DOMAIN_PS;
3089 
3090         setupForDialForDomainSelection(mPhone0, selectedDomain, true);
3091         doReturn(mPhone0).when(mImsPhone).getDefaultPhone();
3092         doReturn(mInternalConnection).when(mPhone0).dial(anyString(), any(), any());
3093 
3094         TestTelephonyConnection c = setupForReDialForDomainSelection(
3095                 mImsPhone, selectedDomain, preciseDisconnectCause, disconnectCause, false);
3096         c.setEmergencyServiceCategory(eccCategory);
3097         c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
3098 
3099         ImsReasonInfo reasonInfo = new ImsReasonInfo(CODE_SIP_ALTERNATE_EMERGENCY_CALL, 0, null);
3100         assertTrue(mTestConnectionService.maybeReselectDomain(c, reasonInfo, true,
3101                 android.telephony.DisconnectCause.NOT_VALID));
3102 
3103         ArgumentCaptor<android.telecom.Connection> connectionCaptor =
3104                 ArgumentCaptor.forClass(android.telecom.Connection.class);
3105 
3106         verify(mDomainSelectionResolver)
3107                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
3108         verify(mEmergencyStateTracker)
3109                 .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
3110         verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), anyBoolean());
3111         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
3112 
3113         android.telecom.Connection tc = connectionCaptor.getValue();
3114 
3115         assertNotNull(tc);
3116         assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
3117         assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
3118 
3119         ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
3120 
3121         verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
3122         DialArgs dialArgs = argsCaptor.getValue();
3123         assertNotNull("DialArgs param is null", dialArgs);
3124         assertNotNull("intentExtras is null", dialArgs.intentExtras);
3125         assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
3126         assertEquals(selectedDomain,
3127                 dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
3128         assertTrue(dialArgs.isEmergency);
3129         assertEquals(eccCategory, dialArgs.eccCategory);
3130         assertTrue(dialArgs.intentExtras.getBoolean(
3131                 PhoneConstants.EXTRA_USE_EMERGENCY_ROUTING, false));
3132     }
3133 
3134     @Test
testDomainSelectionSwitchPhones()3135     public void testDomainSelectionSwitchPhones() throws Exception {
3136         setupForCallTest();
3137 
3138         doReturn(CompletableFuture.completedFuture(EMERGENCY_PERM_FAILURE))
3139                 .when(mEmergencyStateTracker)
3140                 .startEmergencyCall(eq(mPhone0), any(), eq(false));
3141         doReturn(CompletableFuture.completedFuture(NOT_DISCONNECTED))
3142                 .when(mEmergencyStateTracker)
3143                 .startEmergencyCall(eq(mPhone1), any(), eq(false));
3144 
3145         doReturn(mEmergencyCallDomainSelectionConnection).when(mDomainSelectionResolver)
3146                 .getDomainSelectionConnection(any(), anyInt(), eq(true));
3147         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
3148 
3149         doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
3150 
3151         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3152                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
3153                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
3154 
3155         ArgumentCaptor<DomainSelectionService.SelectionAttributes> attrCaptor =
3156                 ArgumentCaptor.forClass(
3157                         DomainSelectionService.SelectionAttributes.class);
3158 
3159         verify(mEmergencyStateTracker).startEmergencyCall(eq(mPhone0), any(), anyBoolean());
3160         verify(mEmergencyStateTracker).startEmergencyCall(eq(mPhone1), any(), anyBoolean());
3161         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(
3162                 attrCaptor.capture(), any());
3163 
3164         DomainSelectionService.SelectionAttributes attr = attrCaptor.getValue();
3165 
3166         assertEquals(mPhone1.getPhoneId(), attr.getSlotIndex());
3167     }
3168 
3169     @Test
testOnSelectionTerminatedPerm()3170     public void testOnSelectionTerminatedPerm() throws Exception {
3171         setupForCallTest();
3172 
3173         doReturn(mEmergencyCallDomainSelectionConnection).when(mDomainSelectionResolver)
3174                 .getDomainSelectionConnection(any(), anyInt(), eq(true));
3175         doReturn(mPhone0).when(mEmergencyCallDomainSelectionConnection).getPhone();
3176         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
3177 
3178         doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
3179         doReturn(mImsPhone).when(mPhone0).getImsPhone();
3180 
3181         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3182                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
3183                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
3184 
3185         ArgumentCaptor<DomainSelectionConnection.DomainSelectionConnectionCallback> callbackCaptor =
3186                 ArgumentCaptor.forClass(
3187                         DomainSelectionConnection.DomainSelectionConnectionCallback.class);
3188 
3189         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(
3190                 any(), callbackCaptor.capture());
3191 
3192         DomainSelectionConnection.DomainSelectionConnectionCallback callback =
3193                 callbackCaptor.getValue();
3194 
3195         assertNotNull(callback);
3196 
3197         EmergencyCallDomainSelectionConnection ecdsc =
3198                 Mockito.mock(EmergencyCallDomainSelectionConnection.class);
3199         doReturn(ecdsc).when(mDomainSelectionResolver)
3200                 .getDomainSelectionConnection(any(), anyInt(), eq(true));
3201 
3202         callback.onSelectionTerminated(EMERGENCY_PERM_FAILURE);
3203 
3204         ArgumentCaptor<DomainSelectionService.SelectionAttributes> attrCaptor =
3205                 ArgumentCaptor.forClass(
3206                         DomainSelectionService.SelectionAttributes.class);
3207 
3208         verify(ecdsc).createEmergencyConnection(attrCaptor.capture(), any());
3209 
3210         DomainSelectionService.SelectionAttributes attr = attrCaptor.getValue();
3211 
3212         assertEquals(mPhone1.getPhoneId(), attr.getSlotIndex());
3213     }
3214 
3215     @Test
testOnSelectionTerminatedTemp()3216     public void testOnSelectionTerminatedTemp() throws Exception {
3217         setupForCallTest();
3218 
3219         doReturn(mEmergencyCallDomainSelectionConnection).when(mDomainSelectionResolver)
3220                 .getDomainSelectionConnection(any(), anyInt(), eq(true));
3221         doReturn(mPhone0).when(mEmergencyCallDomainSelectionConnection).getPhone();
3222         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
3223 
3224         doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
3225         doReturn(mImsPhone).when(mPhone0).getImsPhone();
3226 
3227         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3228                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
3229                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
3230 
3231         ArgumentCaptor<DomainSelectionConnection.DomainSelectionConnectionCallback> callbackCaptor =
3232                 ArgumentCaptor.forClass(
3233                         DomainSelectionConnection.DomainSelectionConnectionCallback.class);
3234 
3235         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(
3236                 any(), callbackCaptor.capture());
3237 
3238         DomainSelectionConnection.DomainSelectionConnectionCallback callback =
3239                 callbackCaptor.getValue();
3240 
3241         assertNotNull(callback);
3242 
3243         EmergencyCallDomainSelectionConnection ecdsc =
3244                 Mockito.mock(EmergencyCallDomainSelectionConnection.class);
3245         doReturn(ecdsc).when(mDomainSelectionResolver)
3246                 .getDomainSelectionConnection(any(), anyInt(), eq(true));
3247 
3248         callback.onSelectionTerminated(EMERGENCY_TEMP_FAILURE);
3249 
3250         ArgumentCaptor<DomainSelectionService.SelectionAttributes> attrCaptor =
3251                 ArgumentCaptor.forClass(
3252                         DomainSelectionService.SelectionAttributes.class);
3253 
3254         verify(ecdsc).createEmergencyConnection(attrCaptor.capture(), any());
3255 
3256         DomainSelectionService.SelectionAttributes attr = attrCaptor.getValue();
3257 
3258         assertEquals(mPhone1.getPhoneId(), attr.getSlotIndex());
3259     }
3260 
3261     @Test
testOnSelectionTerminatedUnspecified()3262     public void testOnSelectionTerminatedUnspecified() throws Exception {
3263         setupForCallTest();
3264 
3265         doReturn(mEmergencyCallDomainSelectionConnection).when(mDomainSelectionResolver)
3266                 .getDomainSelectionConnection(any(), anyInt(), eq(true));
3267         doReturn(mPhone0).when(mEmergencyCallDomainSelectionConnection).getPhone();
3268         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
3269 
3270         doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
3271         doReturn(mImsPhone).when(mPhone0).getImsPhone();
3272 
3273         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3274                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
3275                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
3276 
3277         TelephonyConnection c = mTestConnectionService.getEmergencyConnection();
3278 
3279         assertNotNull(c);
3280         assertNull(c.getOriginalConnection());
3281 
3282         ArgumentCaptor<DomainSelectionConnection.DomainSelectionConnectionCallback> callbackCaptor =
3283                 ArgumentCaptor.forClass(
3284                         DomainSelectionConnection.DomainSelectionConnectionCallback.class);
3285 
3286         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(
3287                 any(), callbackCaptor.capture());
3288 
3289         DomainSelectionConnection.DomainSelectionConnectionCallback callback =
3290                 callbackCaptor.getValue();
3291 
3292         assertNotNull(callback);
3293 
3294         callback.onSelectionTerminated(ERROR_UNSPECIFIED);
3295 
3296         verify(mEmergencyCallDomainSelectionConnection).cancelSelection();
3297         verify(mEmergencyStateTracker).endCall(eq(c));
3298 
3299         android.telecom.DisconnectCause disconnectCause = c.getDisconnectCause();
3300 
3301         assertNotNull(disconnectCause);
3302         assertEquals(ERROR_UNSPECIFIED, disconnectCause.getTelephonyDisconnectCause());
3303     }
3304 
3305     @Test
testDomainSelectionDialFailedByException()3306     public void testDomainSelectionDialFailedByException() throws Exception {
3307         setupForCallTest();
3308 
3309         int selectedDomain = DOMAIN_CS;
3310 
3311         setupForDialForDomainSelection(mPhone0, selectedDomain, true);
3312 
3313         CallStateException cse = new CallStateException(CallStateException.ERROR_CALLING_DISABLED,
3314                 "Calling disabled via ro.telephony.disable-call property");
3315         doThrow(cse).when(mPhone0).dial(anyString(), any(), any());
3316 
3317         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3318                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
3319                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
3320 
3321         verify(mEmergencyStateTracker)
3322                 .startEmergencyCall(any(), any(), anyBoolean());
3323         verify(mEmergencyCallDomainSelectionConnection).cancelSelection();
3324         verify(mEmergencyStateTracker).endCall(any());
3325     }
3326 
3327     @Test
testDomainSelectionLocalHangupStartEmergencyCall()3328     public void testDomainSelectionLocalHangupStartEmergencyCall() throws Exception {
3329         setupForCallTest();
3330 
3331         int selectedDomain = DOMAIN_CS;
3332 
3333         setupForDialForDomainSelection(mPhone0, selectedDomain, true);
3334 
3335         CompletableFuture<Integer> future = new CompletableFuture<>();
3336         doReturn(future).when(mEmergencyStateTracker)
3337                 .startEmergencyCall(any(), any(), eq(false));
3338 
3339         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3340                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
3341                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
3342 
3343         verify(mEmergencyStateTracker)
3344                 .startEmergencyCall(eq(mPhone0), any(), eq(false));
3345 
3346         // dialing is canceled
3347         mTestConnectionService.onLocalHangup(mTestConnectionService.getEmergencyConnection());
3348 
3349         // startEmergencyCall has completed
3350         future.complete(NOT_DISCONNECTED);
3351 
3352         // verify that createEmergencyConnection is discarded
3353         verify(mEmergencyCallDomainSelectionConnection, never())
3354                 .createEmergencyConnection(any(), any());
3355     }
3356 
3357     @Test
testDomainSelectionLocalHangupCreateEmergencyConnection()3358     public void testDomainSelectionLocalHangupCreateEmergencyConnection() throws Exception {
3359         setupForCallTest();
3360 
3361         int selectedDomain = DOMAIN_CS;
3362 
3363         setupForDialForDomainSelection(mPhone0, selectedDomain, true);
3364 
3365         CompletableFuture<Integer> future = new CompletableFuture<>();
3366         doReturn(future).when(mEmergencyCallDomainSelectionConnection)
3367                 .createEmergencyConnection(any(), any());
3368 
3369         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3370                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
3371                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
3372 
3373         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
3374 
3375         // dialing is canceled
3376         mTestConnectionService.onLocalHangup(mTestConnectionService.getEmergencyConnection());
3377 
3378         // domain selection has completed
3379         future.complete(selectedDomain);
3380 
3381         // verify that dialing is discarded
3382         verify(mPhone0, never()).dial(anyString(), any(), any());
3383     }
3384 
3385     @Test
testDomainSelectionRedialLocalHangupReselectDomain()3386     public void testDomainSelectionRedialLocalHangupReselectDomain() throws Exception {
3387         setupForCallTest();
3388 
3389         int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
3390         int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
3391         int selectedDomain = DOMAIN_CS;
3392 
3393         TestTelephonyConnection c = setupForReDialForDomainSelection(
3394                 mPhone0, selectedDomain, preciseDisconnectCause, disconnectCause, true);
3395 
3396         CompletableFuture<Integer> future = new CompletableFuture<>();
3397         doReturn(future).when(mEmergencyCallDomainSelectionConnection)
3398                 .reselectDomain(any());
3399 
3400         assertTrue(mTestConnectionService.maybeReselectDomain(c, null, true,
3401                 android.telephony.DisconnectCause.NOT_VALID));
3402         verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
3403 
3404         // dialing is canceled
3405         mTestConnectionService.onLocalHangup(c);
3406 
3407         // domain selection has completed
3408         future.complete(selectedDomain);
3409 
3410         // verify that dialing is discarded
3411         verify(mPhone0, times(0)).dial(anyString(), any(), any());
3412     }
3413 
3414     @Test
testDomainSelectionNormalToEmergencyLocalHangupStartEmergencyCall()3415     public void testDomainSelectionNormalToEmergencyLocalHangupStartEmergencyCall()
3416             throws Exception {
3417         setupForCallTest();
3418 
3419         int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
3420         int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
3421         int eccCategory = EMERGENCY_SERVICE_CATEGORY_POLICE;
3422         int selectedDomain = DOMAIN_CS;
3423 
3424         setupForDialForDomainSelection(mPhone0, selectedDomain, true);
3425         doReturn(mPhone0).when(mImsPhone).getDefaultPhone();
3426 
3427         TestTelephonyConnection c = setupForReDialForDomainSelection(
3428                 mImsPhone, selectedDomain, preciseDisconnectCause, disconnectCause, false);
3429         c.setEmergencyServiceCategory(eccCategory);
3430         c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
3431 
3432         CompletableFuture<Integer> future = new CompletableFuture<>();
3433         doReturn(future).when(mEmergencyStateTracker)
3434                 .startEmergencyCall(any(), any(), eq(false));
3435 
3436         ImsReasonInfo reasonInfo = new ImsReasonInfo(CODE_SIP_ALTERNATE_EMERGENCY_CALL, 0, null);
3437         assertTrue(mTestConnectionService.maybeReselectDomain(c, reasonInfo, true,
3438                 android.telephony.DisconnectCause.NOT_VALID));
3439 
3440         ArgumentCaptor<android.telecom.Connection> connectionCaptor =
3441                 ArgumentCaptor.forClass(android.telecom.Connection.class);
3442 
3443         verify(mEmergencyStateTracker)
3444                 .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
3445         verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), anyBoolean());
3446 
3447         android.telecom.Connection tc = connectionCaptor.getValue();
3448 
3449         assertNotNull(tc);
3450         assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
3451         assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
3452 
3453         // dialing is canceled
3454         mTestConnectionService.onLocalHangup(c);
3455 
3456         // startEmergencyCall has completed
3457         future.complete(NOT_DISCONNECTED);
3458 
3459         // verify that createEmergencyConnection is discarded
3460         verify(mEmergencyCallDomainSelectionConnection, times(0))
3461                 .createEmergencyConnection(any(), any());
3462     }
3463 
3464     @Test
testDomainSelectionNormalToEmergencyLocalHangupCreateEmergencyConnection()3465     public void testDomainSelectionNormalToEmergencyLocalHangupCreateEmergencyConnection()
3466             throws Exception {
3467         setupForCallTest();
3468 
3469         int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
3470         int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
3471         int eccCategory = EMERGENCY_SERVICE_CATEGORY_POLICE;
3472         int selectedDomain = DOMAIN_CS;
3473 
3474         setupForDialForDomainSelection(mPhone0, selectedDomain, true);
3475         doReturn(mPhone0).when(mImsPhone).getDefaultPhone();
3476 
3477         TestTelephonyConnection c = setupForReDialForDomainSelection(
3478                 mImsPhone, selectedDomain, preciseDisconnectCause, disconnectCause, false);
3479         c.setEmergencyServiceCategory(eccCategory);
3480         c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
3481 
3482         CompletableFuture<Integer> future = new CompletableFuture<>();
3483         doReturn(future).when(mEmergencyCallDomainSelectionConnection)
3484                 .createEmergencyConnection(any(), any());
3485 
3486         ImsReasonInfo reasonInfo = new ImsReasonInfo(CODE_SIP_ALTERNATE_EMERGENCY_CALL, 0, null);
3487         assertTrue(mTestConnectionService.maybeReselectDomain(c, reasonInfo, true,
3488                 android.telephony.DisconnectCause.NOT_VALID));
3489 
3490         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
3491 
3492         // dialing is canceled
3493         mTestConnectionService.onLocalHangup(c);
3494 
3495         // domain selection has completed
3496         future.complete(selectedDomain);
3497 
3498         // verify that dialing is discarded
3499         verify(mPhone0, never()).dial(anyString(), any(), any());
3500     }
3501 
3502     @Test
testDomainSelectionListenOriginalConnectionConfigChange()3503     public void testDomainSelectionListenOriginalConnectionConfigChange() throws Exception {
3504         setupForCallTest();
3505 
3506         int selectedDomain = DOMAIN_PS;
3507 
3508         setupForDialForDomainSelection(mPhone0, selectedDomain, true);
3509 
3510         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3511                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
3512                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
3513 
3514         ArgumentCaptor<android.telecom.Connection> connectionCaptor =
3515                 ArgumentCaptor.forClass(android.telecom.Connection.class);
3516 
3517         verify(mDomainSelectionResolver)
3518                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
3519         verify(mEmergencyStateTracker)
3520                 .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
3521         verify(mSatelliteSOSMessageRecommender, times(2)).onEmergencyCallStarted(any(),
3522                 anyBoolean());
3523         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
3524         verify(mPhone0).dial(anyString(), any(), any());
3525 
3526         android.telecom.Connection tc = connectionCaptor.getValue();
3527 
3528         assertNotNull(tc);
3529         assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
3530         assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
3531 
3532         TestTelephonyConnection c = new TestTelephonyConnection();
3533         mTestConnectionService.setEmergencyConnection(c);
3534         c.setTelecomCallId(TELECOM_CALL_ID1);
3535         c.setIsImsConnection(true);
3536         Connection orgConn = c.getOriginalConnection();
3537         doReturn(PhoneConstants.PHONE_TYPE_IMS).when(orgConn).getPhoneType();
3538 
3539         TelephonyConnection.TelephonyConnectionListener connectionListener =
3540                 mTestConnectionService.getEmergencyConnectionListener();
3541         TelephonyConnection.TelephonyConnectionListener connectionSatelliteListener =
3542                 mTestConnectionService.getEmergencyConnectionSatelliteListener();
3543 
3544         connectionListener.onOriginalConnectionConfigured(c);
3545 
3546         verify(mEmergencyStateTracker, times(1)).onEmergencyCallDomainUpdated(
3547                 eq(PhoneConstants.PHONE_TYPE_IMS), eq(c));
3548 
3549         verify(mEmergencyStateTracker, times(0)).onEmergencyCallStateChanged(
3550                 any(), eq(c));
3551         verify(mSatelliteSOSMessageRecommender, times(2))
3552                 .onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1), anyInt());
3553 
3554         c.setActive();
3555         doReturn(Call.State.ACTIVE).when(orgConn).getState();
3556         connectionListener.onStateChanged(c, c.getState());
3557         connectionSatelliteListener.onStateChanged(c, c.getState());
3558 
3559         // ACTIVE sate is notified
3560         verify(mEmergencyStateTracker, times(1)).onEmergencyCallStateChanged(
3561                 eq(Call.State.ACTIVE), eq(c));
3562         verify(mSatelliteSOSMessageRecommender, times(1))
3563                 .onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1),
3564                         eq(android.telecom.Connection.STATE_ACTIVE));
3565 
3566         // state change to HOLDING
3567         c.setOnHold();
3568         doReturn(Call.State.HOLDING).when(orgConn).getState();
3569         connectionListener.onStateChanged(c, c.getState());
3570         connectionSatelliteListener.onStateChanged(c, c.getState());
3571 
3572         // state change not notified any more after CONNECTED once
3573         verify(mEmergencyStateTracker, times(1)).onEmergencyCallStateChanged(
3574                 any(), eq(c));
3575         verify(mSatelliteSOSMessageRecommender, times(3))
3576                 .onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1), anyInt());
3577 
3578         // state change to ACTIVE again
3579         c.setActive();
3580         doReturn(Call.State.ACTIVE).when(orgConn).getState();
3581         connectionListener.onStateChanged(c, c.getState());
3582         connectionSatelliteListener.onStateChanged(c, c.getState());
3583 
3584         // state change not notified any more after CONNECTED once
3585         verify(mEmergencyStateTracker, times(1)).onEmergencyCallStateChanged(
3586                 any(), eq(c));
3587         verify(mSatelliteSOSMessageRecommender, times(3))
3588                 .onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1), anyInt());
3589 
3590         // SRVCC happens
3591         c.setIsImsConnection(false);
3592         orgConn = c.getOriginalConnection();
3593         doReturn(PhoneConstants.PHONE_TYPE_GSM).when(orgConn).getPhoneType();
3594         connectionListener.onOriginalConnectionConfigured(c);
3595 
3596          // domain change notified
3597         verify(mEmergencyStateTracker, times(1)).onEmergencyCallDomainUpdated(
3598                 eq(PhoneConstants.PHONE_TYPE_GSM), eq(c));
3599 
3600         // state change to DISCONNECTED
3601         c.setDisconnected(null);
3602         doReturn(Call.State.DISCONNECTED).when(orgConn).getState();
3603         connectionListener.onStateChanged(c, c.getState());
3604         connectionSatelliteListener.onStateChanged(c, c.getState());
3605 
3606         // state change not notified
3607         verify(mEmergencyStateTracker, times(1)).onEmergencyCallStateChanged(
3608                 any(), eq(c));
3609         verify(mSatelliteSOSMessageRecommender, times(3))
3610                 .onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1), anyInt());
3611     }
3612 
3613     @Test
testDomainSelectionListenOriginalConnectionPropertiesChange()3614     public void testDomainSelectionListenOriginalConnectionPropertiesChange() throws Exception {
3615         setupForCallTest();
3616 
3617         int selectedDomain = DOMAIN_PS;
3618 
3619         setupForDialForDomainSelection(mPhone0, selectedDomain, true);
3620 
3621         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3622                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
3623                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
3624 
3625         ArgumentCaptor<android.telecom.Connection> connectionCaptor =
3626                 ArgumentCaptor.forClass(android.telecom.Connection.class);
3627 
3628         verify(mDomainSelectionResolver)
3629                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
3630         verify(mEmergencyStateTracker)
3631                 .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
3632         verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
3633         verify(mPhone0).dial(anyString(), any(), any());
3634 
3635         android.telecom.Connection tc = connectionCaptor.getValue();
3636 
3637         assertNotNull(tc);
3638         assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
3639         assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
3640 
3641         TestTelephonyConnection c = new TestTelephonyConnection();
3642         mTestConnectionService.setEmergencyConnection(c);
3643         c.setIsImsConnection(true);
3644         Connection orgConn = c.getOriginalConnection();
3645         doReturn(PhoneConstants.PHONE_TYPE_IMS).when(orgConn).getPhoneType();
3646 
3647         TelephonyConnection.TelephonyConnectionListener connectionListener =
3648                 mTestConnectionService.getEmergencyConnectionListener();
3649 
3650         doReturn(Call.State.DISCONNECTING).when(orgConn).getState();
3651         connectionListener.onConnectionPropertiesChanged(c, PROPERTY_WIFI);
3652 
3653         verify(mEmergencyStateTracker, times(0)).onEmergencyCallPropertiesChanged(
3654                 anyInt(), any());
3655 
3656         doReturn(Call.State.ACTIVE).when(orgConn).getState();
3657         connectionListener.onConnectionPropertiesChanged(c, PROPERTY_WIFI);
3658 
3659         verify(mEmergencyStateTracker, times(1)).onEmergencyCallPropertiesChanged(
3660                 eq(PROPERTY_WIFI), eq(c));
3661 
3662         connectionListener.onConnectionPropertiesChanged(c, 0);
3663 
3664         verify(mEmergencyStateTracker, times(1)).onEmergencyCallPropertiesChanged(
3665                 eq(0), eq(c));
3666     }
3667 
3668     @Test
testDomainSelectionTempFailure()3669     public void testDomainSelectionTempFailure() throws Exception {
3670         setupForCallTest();
3671 
3672         int preciseDisconnectCause =
3673                 com.android.internal.telephony.CallFailCause.EMERGENCY_TEMP_FAILURE;
3674         int disconnectCause = android.telephony.DisconnectCause.EMERGENCY_TEMP_FAILURE;
3675         int selectedDomain = DOMAIN_CS;
3676 
3677         TestTelephonyConnection c = setupForReDialForDomainSelection(
3678                 mPhone0, selectedDomain, preciseDisconnectCause, disconnectCause, true);
3679 
3680         doReturn(new CompletableFuture()).when(mEmergencyCallDomainSelectionConnection)
3681                 .reselectDomain(any());
3682 
3683         assertTrue(mTestConnectionService.maybeReselectDomain(c, null, true,
3684                 android.telephony.DisconnectCause.NOT_VALID));
3685         verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
3686     }
3687 
3688     @Test
testDomainSelectionPermFailure()3689     public void testDomainSelectionPermFailure() throws Exception {
3690         setupForCallTest();
3691 
3692         int preciseDisconnectCause =
3693                 com.android.internal.telephony.CallFailCause.EMERGENCY_PERM_FAILURE;
3694         int disconnectCause = android.telephony.DisconnectCause.EMERGENCY_PERM_FAILURE;
3695         int selectedDomain = DOMAIN_CS;
3696 
3697         TestTelephonyConnection c = setupForReDialForDomainSelection(
3698                 mPhone0, selectedDomain, preciseDisconnectCause, disconnectCause, true);
3699 
3700         doReturn(new CompletableFuture()).when(mEmergencyCallDomainSelectionConnection)
3701                 .reselectDomain(any());
3702 
3703         assertTrue(mTestConnectionService.maybeReselectDomain(c, null, true,
3704                 android.telephony.DisconnectCause.NOT_VALID));
3705         verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
3706     }
3707 
3708     @Test
testDomainSelectionWithMmiCode()3709     public void testDomainSelectionWithMmiCode() {
3710         //UT domain selection should not be handled by new domain selector.
3711         doNothing().when(mContext).startActivityAsUser(any(), any());
3712         setupForCallTest();
3713         setupForDialForDomainSelection(mPhone0, 0, false);
3714         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3715                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "*%2321%23", TELECOM_CALL_ID1));
3716 
3717         verifyZeroInteractions(mNormalCallDomainSelectionConnection);
3718     }
3719 
3720     @Test
testNormalCallPsDomainSelection()3721     public void testNormalCallPsDomainSelection() throws Exception {
3722         setupForCallTest();
3723         int selectedDomain = DOMAIN_PS;
3724         setupForDialForDomainSelection(mPhone0, selectedDomain, false);
3725 
3726         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3727                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", TELECOM_CALL_ID1));
3728 
3729         verify(mDomainSelectionResolver)
3730                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(false));
3731         verify(mNormalCallDomainSelectionConnection).createNormalConnection(any(), any());
3732         verify(mSatelliteSOSMessageRecommender, never()).onEmergencyCallStarted(any(),
3733                 anyBoolean());
3734 
3735         ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
3736 
3737         verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
3738         DialArgs dialArgs = argsCaptor.getValue();
3739         assertNotNull("DialArgs param is null", dialArgs);
3740         assertNotNull("intentExtras is null", dialArgs.intentExtras);
3741         assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
3742         assertEquals(
3743                 selectedDomain, dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
3744     }
3745 
3746     @Test
testNormalCallCsDomainSelection()3747     public void testNormalCallCsDomainSelection() throws Exception {
3748         setupForCallTest();
3749         int selectedDomain = DOMAIN_CS;
3750         setupForDialForDomainSelection(mPhone0, selectedDomain, false);
3751 
3752         mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3753                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", TELECOM_CALL_ID1));
3754 
3755         verify(mDomainSelectionResolver)
3756                 .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(false));
3757         verify(mNormalCallDomainSelectionConnection).createNormalConnection(any(), any());
3758         verify(mSatelliteSOSMessageRecommender, never()).onEmergencyCallStarted(any(),
3759                 anyBoolean());
3760 
3761         ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
3762 
3763         verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
3764         DialArgs dialArgs = argsCaptor.getValue();
3765         assertNotNull("DialArgs param is null", dialArgs);
3766         assertNotNull("intentExtras is null", dialArgs.intentExtras);
3767         assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
3768         assertEquals(
3769                 selectedDomain, dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
3770     }
3771 
3772     @Test
testNormalCallSatelliteEnabled()3773     public void testNormalCallSatelliteEnabled() {
3774         setupForCallTest();
3775         doReturn(true).when(mSatelliteController).isSatelliteEnabledOrBeingEnabled();
3776 
3777         mConnection = mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3778                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", TELECOM_CALL_ID1));
3779         DisconnectCause disconnectCause = mConnection.getDisconnectCause();
3780         assertEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
3781                 disconnectCause.getTelephonyDisconnectCause());
3782         assertEquals(DISCONNECT_REASON_SATELLITE_ENABLED, disconnectCause.getReason());
3783     }
3784 
3785     @Test
testEmergencyCallSatelliteEnabled_blockEmergencyCall()3786     public void testEmergencyCallSatelliteEnabled_blockEmergencyCall() {
3787         setupForCallTest();
3788         doReturn(true).when(mSatelliteController).isSatelliteEnabledOrBeingEnabled();
3789         doReturn(false).when(mMockResources).getBoolean(anyInt());
3790         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(
3791                 anyString());
3792 
3793         // Simulates an outgoing emergency call.
3794         mConnection = mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3795                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
3796                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
3797         DisconnectCause disconnectCause = mConnection.getDisconnectCause();
3798         assertEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
3799                 disconnectCause.getTelephonyDisconnectCause());
3800         assertEquals(DISCONNECT_REASON_SATELLITE_ENABLED, disconnectCause.getReason());
3801     }
3802 
3803     @Test
testNormalCallUsingNonTerrestrialNetwork_enableFlag()3804     public void testNormalCallUsingNonTerrestrialNetwork_enableFlag() throws Exception {
3805         mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
3806 
3807         setupForCallTest();
3808         // Call is not supported while using satellite
3809         when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
3810         when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any()))
3811                 .thenReturn(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA));
3812 
3813         mConnection = mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3814                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", TELECOM_CALL_ID1));
3815         DisconnectCause disconnectCause = mConnection.getDisconnectCause();
3816         assertEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
3817                 disconnectCause.getTelephonyDisconnectCause());
3818         assertEquals(DISCONNECT_REASON_CARRIER_ROAMING_SATELLITE_MODE, disconnectCause.getReason());
3819 
3820         // Call is supported while using satellite
3821         when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any()))
3822                 .thenReturn(List.of(NetworkRegistrationInfo.SERVICE_TYPE_VOICE));
3823 
3824         // UnsupportedOperationException is thrown as we cannot perform actual call
3825         assertThrows(UnsupportedOperationException.class, () -> mTestConnectionService
3826                 .onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3827                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", "TC@2")));
3828     }
3829 
3830     @Test
testNormalCallUsingSatelliteConnectedWithinHysteresisTime()3831     public void testNormalCallUsingSatelliteConnectedWithinHysteresisTime() throws Exception {
3832         mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
3833 
3834         // Call is not supported when device is connected to satellite within hysteresis time
3835         setupForCallTest();
3836         when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
3837         when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any()))
3838                 .thenReturn(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA));
3839 
3840         mConnection = mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3841                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", TELECOM_CALL_ID1));
3842         DisconnectCause disconnectCause = mConnection.getDisconnectCause();
3843         assertEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
3844                 disconnectCause.getTelephonyDisconnectCause());
3845         assertEquals(DISCONNECT_REASON_CARRIER_ROAMING_SATELLITE_MODE, disconnectCause.getReason());
3846 
3847         // Call is supported when device is connected to satellite within hysteresis time
3848         setupForCallTest();
3849         when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any())).thenReturn(
3850                 List.of(NetworkRegistrationInfo.SERVICE_TYPE_VOICE));
3851 
3852         // UnsupportedOperationException is thrown as we cannot perform actual call
3853         assertThrows(UnsupportedOperationException.class, () -> mTestConnectionService
3854                 .onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3855                         createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", "TC@2")));
3856     }
3857 
3858     @Test
testNormalCallUsingNonTerrestrialNetwork_disableFlag()3859     public void testNormalCallUsingNonTerrestrialNetwork_disableFlag() throws Exception {
3860         mSetFlagsRule.disableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
3861 
3862         setupForCallTest();
3863         // Flag is disabled, so call is supported while using satellite
3864         when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
3865         when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any())).thenReturn(
3866                 List.of(NetworkRegistrationInfo.SERVICE_TYPE_VOICE));
3867 
3868         // UnsupportedOperationException is thrown as we cannot perform actual call
3869         assertThrows(UnsupportedOperationException.class, () -> mTestConnectionService
3870                 .onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3871                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", TELECOM_CALL_ID1)));
3872     }
3873 
3874     @Test
testNormalCallUsingNonTerrestrialNetwork_canMakeWifiCall()3875     public void testNormalCallUsingNonTerrestrialNetwork_canMakeWifiCall() throws Exception {
3876         mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
3877 
3878         setupForCallTest();
3879         // Call is not supported while using satellite
3880         when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
3881         when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any()))
3882                 .thenReturn(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA));
3883         // Wi-Fi call is possible
3884         doReturn(true).when(mImsPhone).canMakeWifiCall();
3885         when(mPhone0.getImsPhone()).thenReturn(mImsPhone);
3886 
3887         // UnsupportedOperationException is thrown as we cannot perform actual call
3888         assertThrows(UnsupportedOperationException.class, () -> mTestConnectionService
3889                 .onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
3890                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", TELECOM_CALL_ID1)));
3891     }
3892 
3893     @Test
testIsAvailableForEmergencyCallsNotForCrossSim()3894     public void testIsAvailableForEmergencyCallsNotForCrossSim() {
3895         Phone mockPhone = Mockito.mock(Phone.class);
3896         when(mockPhone.getImsRegistrationTech()).thenReturn(
3897                 ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM);
3898         assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
3899                 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY));
3900         assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
3901                 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL));
3902         assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
3903                 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
3904     }
3905 
3906     @Test
testIsAvailableForEmergencyCallsUsingNonTerrestrialNetwork_enableFlag()3907     public void testIsAvailableForEmergencyCallsUsingNonTerrestrialNetwork_enableFlag() {
3908         mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
3909 
3910         // Call is not supported while using satellite
3911         when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
3912         when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any()))
3913                 .thenReturn(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA));
3914         Phone mockPhone = Mockito.mock(Phone.class);
3915         ServiceState ss = new ServiceState();
3916         ss.setEmergencyOnly(true);
3917         ss.setState(ServiceState.STATE_EMERGENCY_ONLY);
3918         when(mockPhone.getServiceState()).thenReturn(ss);
3919         when(mPhoneFactoryProxy.getPhones()).thenReturn(new Phone[] {mockPhone});
3920 
3921         assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
3922                 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY));
3923         assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
3924                 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL));
3925         assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
3926                 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
3927     }
3928 
3929     @Test
testIsAvailableForEmergencyCallsUsingNonTerrestrialNetwork_disableFlag()3930     public void testIsAvailableForEmergencyCallsUsingNonTerrestrialNetwork_disableFlag() {
3931         mSetFlagsRule.disableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
3932 
3933         // Call is supported while using satellite
3934         when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
3935         when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any()))
3936                 .thenReturn(List.of(NetworkRegistrationInfo.SERVICE_TYPE_VOICE));
3937         Phone mockPhone = Mockito.mock(Phone.class);
3938         ServiceState ss = new ServiceState();
3939         ss.setEmergencyOnly(true);
3940         ss.setState(ServiceState.STATE_EMERGENCY_ONLY);
3941         when(mockPhone.getServiceState()).thenReturn(ss);
3942 
3943         when(mPhoneFactoryProxy.getPhones()).thenReturn(new Phone[] {mockPhone});
3944 
3945         assertTrue(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
3946                 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY));
3947         assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
3948                 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL));
3949         assertTrue(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
3950                 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
3951     }
3952 
3953     @Test
testIsAvailableForEmergencyCallsUsingNTN_CellularAvailable()3954     public void testIsAvailableForEmergencyCallsUsingNTN_CellularAvailable() {
3955         mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
3956 
3957         // Call is not supported while using satellite
3958         when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
3959         when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any()))
3960                 .thenReturn(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA));
3961 
3962         Phone mockPhone = Mockito.mock(Phone.class);
3963         ServiceState ss = new ServiceState();
3964         ss.setEmergencyOnly(true);
3965         ss.setState(ServiceState.STATE_EMERGENCY_ONLY);
3966         when(mockPhone.getServiceState()).thenReturn(ss);
3967 
3968         // Phone2 is in limited service
3969         Phone mockPhone2 = Mockito.mock(Phone.class);
3970         ServiceState ss2 = new ServiceState();
3971         ss2.setEmergencyOnly(true);
3972         ss2.setState(ServiceState.STATE_EMERGENCY_ONLY);
3973         when(mockPhone2.getServiceState()).thenReturn(ss2);
3974 
3975         Phone[] phones = {mockPhone, mockPhone2};
3976         when(mPhoneFactoryProxy.getPhones()).thenReturn(phones);
3977 
3978         assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
3979                 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY));
3980         assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
3981                 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL));
3982         assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
3983                 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
3984     }
3985 
3986     @Test
testIsAvailableForEmergencyCallsUsingNTN_CellularNotAvailable()3987     public void testIsAvailableForEmergencyCallsUsingNTN_CellularNotAvailable() {
3988         mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
3989 
3990         // Call is not supported while using satellite
3991         when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
3992         when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any()))
3993                 .thenReturn(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA));
3994 
3995         NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
3996                 .setIsNonTerrestrialNetwork(true)
3997                 .setAvailableServices(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA))
3998                 .build();
3999         Phone mockPhone = Mockito.mock(Phone.class);
4000         ServiceState ss = new ServiceState();
4001         ss.addNetworkRegistrationInfo(nri);
4002         ss.setEmergencyOnly(true);
4003         ss.setState(ServiceState.STATE_EMERGENCY_ONLY);
4004         when(mockPhone.getServiceState()).thenReturn(ss);
4005 
4006         // Phone2 is out of service
4007         Phone mockPhone2 = Mockito.mock(Phone.class);
4008         ServiceState ss2 = new ServiceState();
4009         ss2.setEmergencyOnly(false);
4010         ss2.setState(ServiceState.STATE_OUT_OF_SERVICE);
4011         when(mockPhone2.getServiceState()).thenReturn(ss2);
4012 
4013         Phone[] phones = {mockPhone, mockPhone2};
4014         when(mPhoneFactoryProxy.getPhones()).thenReturn(phones);
4015 
4016         assertTrue(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
4017                 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY));
4018         assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
4019                 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL));
4020         assertTrue(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
4021                 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
4022     }
4023 
4024     @Test
testIsAvailableForEmergencyCallsForEmergencyRoutingInEmergencyOnly()4025     public void testIsAvailableForEmergencyCallsForEmergencyRoutingInEmergencyOnly() {
4026         ServiceState mockService = Mockito.mock(ServiceState.class);
4027         when(mockService.isEmergencyOnly()).thenReturn(true);
4028         when(mockService.getState()).thenReturn(ServiceState.STATE_EMERGENCY_ONLY);
4029 
4030         Phone mockPhone = Mockito.mock(Phone.class);
4031         when(mockPhone.getImsRegistrationTech()).thenReturn(
4032                 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
4033         when(mockPhone.getServiceState()).thenReturn(mockService);
4034 
4035         assertTrue(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
4036                 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY));
4037         assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
4038                 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL));
4039         assertTrue(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
4040                 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
4041     }
4042 
4043     @Test
testIsAvailableForEmergencyCallsForEmergencyRoutingInService()4044     public void testIsAvailableForEmergencyCallsForEmergencyRoutingInService() {
4045         ServiceState mockService = Mockito.mock(ServiceState.class);
4046         when(mockService.isEmergencyOnly()).thenReturn(false);
4047         when(mockService.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
4048 
4049         Phone mockPhone = Mockito.mock(Phone.class);
4050         when(mockPhone.getImsRegistrationTech()).thenReturn(
4051                 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
4052         when(mockPhone.getServiceState()).thenReturn(mockService);
4053 
4054         assertTrue(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
4055                 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY));
4056         assertTrue(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
4057                 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL));
4058         assertTrue(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
4059                 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
4060     }
4061 
4062     /**
4063      * Verify that is the carrier config indicates that the carrier does not prefer to use an in
4064      * service sim for a normal routed emergency call that we'll get no result.
4065      */
4066     @Test
testGetPhoneForNormalRoutedEmergencyCallWhenCarrierDoesntSupport()4067     public void testGetPhoneForNormalRoutedEmergencyCallWhenCarrierDoesntSupport() {
4068         ServiceState mockService = Mockito.mock(ServiceState.class);
4069         when(mockService.isEmergencyOnly()).thenReturn(false);
4070         when(mockService.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
4071 
4072         Phone mockPhone = Mockito.mock(Phone.class);
4073         when(mockPhone.shouldPreferInServiceSimForNormalRoutedEmergencyCall()).thenReturn(
4074                 false);
4075         setupMockEmergencyNumbers(mockPhone, List.of(MOCK_NORMAL_NUMBER));
4076         when(mPhoneFactoryProxy.getPhones()).thenReturn(new Phone[] {mockPhone});
4077 
4078         assertNull(mTestConnectionService.getPhoneForNormalRoutedEmergencyCall(
4079                 NORMAL_ROUTED_EMERGENCY_NUMBER));
4080     }
4081 
4082     /**
4083      * Verify that is the carrier config indicates that the carrier prefers to use an in service sim
4084      * for a normal routed emergency call that we'll get the in service sim that supports it.
4085      */
4086     @Test
testGetPhoneForNormalRoutedEmergencyCallWhenCarrierDoesSupport()4087     public void testGetPhoneForNormalRoutedEmergencyCallWhenCarrierDoesSupport() {
4088         ServiceState mockService = Mockito.mock(ServiceState.class);
4089         when(mockService.isEmergencyOnly()).thenReturn(false);
4090         when(mockService.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
4091 
4092         Phone mockPhone = Mockito.mock(Phone.class);
4093         when(mockPhone.shouldPreferInServiceSimForNormalRoutedEmergencyCall()).thenReturn(
4094                 true);
4095         when(mockPhone.getServiceState()).thenReturn(mockService);
4096         setupMockEmergencyNumbers(mockPhone, List.of(MOCK_NORMAL_NUMBER));
4097         when(mPhoneFactoryProxy.getPhones()).thenReturn(new Phone[] {mockPhone});
4098 
4099         assertEquals(mockPhone,
4100                 mTestConnectionService.getPhoneForNormalRoutedEmergencyCall(
4101                         NORMAL_ROUTED_EMERGENCY_NUMBER));
4102     }
4103 
4104     /**
4105      * Verify where there are two sims, one in limited service, and another in full service, if the
4106      * carrier prefers to use an in-service sim, we choose the in-service sim.
4107      */
4108     @Test
testGetPhoneForNormalRoutedEmergencyCallWhenCarrierDoesSupportMultiSim()4109     public void testGetPhoneForNormalRoutedEmergencyCallWhenCarrierDoesSupportMultiSim() {
4110         ServiceState mockInService = Mockito.mock(ServiceState.class);
4111         when(mockInService.isEmergencyOnly()).thenReturn(false);
4112         when(mockInService.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
4113         ServiceState mockLimitedService = Mockito.mock(ServiceState.class);
4114         when(mockLimitedService.isEmergencyOnly()).thenReturn(true);
4115         when(mockLimitedService.getState()).thenReturn(ServiceState.STATE_EMERGENCY_ONLY);
4116 
4117         Phone mockInservicePhone = Mockito.mock(Phone.class);
4118         when(mockInservicePhone.shouldPreferInServiceSimForNormalRoutedEmergencyCall()).thenReturn(
4119                 true);
4120         when(mockInservicePhone.getServiceState()).thenReturn(mockInService);
4121         setupMockEmergencyNumbers(mockInservicePhone, List.of(MOCK_NORMAL_NUMBER));
4122 
4123         Phone mockLimitedServicePhone = Mockito.mock(Phone.class);
4124         when(mockLimitedServicePhone.shouldPreferInServiceSimForNormalRoutedEmergencyCall())
4125                 .thenReturn(true);
4126         when(mockLimitedServicePhone.getServiceState()).thenReturn(mockLimitedService);
4127         setupMockEmergencyNumbers(mockLimitedServicePhone, List.of(MOCK_NORMAL_NUMBER));
4128 
4129         when(mPhoneFactoryProxy.getPhones()).thenReturn(new Phone[] {mockLimitedServicePhone,
4130                 mockInservicePhone});
4131 
4132         assertEquals(mockInservicePhone,
4133                 mTestConnectionService.getPhoneForNormalRoutedEmergencyCall(
4134                         NORMAL_ROUTED_EMERGENCY_NUMBER));
4135     }
4136 
4137     /**
4138      * Verify where there are two sims, we choose the sim in emergency callback mode for the
4139      * next emergency call.
4140      */
4141     @Test
testGetPhoneInEmergencyCallbackModeMultiSim()4142     public void testGetPhoneInEmergencyCallbackModeMultiSim() {
4143         Phone mockPhone1 = Mockito.mock(Phone.class);
4144         Phone mockPhone2 = Mockito.mock(Phone.class);
4145 
4146         when(mPhoneFactoryProxy.getPhones()).thenReturn(
4147                 new Phone[] {mockPhone1, mockPhone2});
4148 
4149         doReturn(false).when(mEmergencyStateTracker).isInEcm(eq(mockPhone1));
4150         doReturn(true).when(mEmergencyStateTracker).isInEcm(eq(mockPhone2));
4151 
4152         // Only applicable for AP domain seleciton service
4153         assertNull(mTestConnectionService.getPhoneInEmergencyCallbackMode());
4154 
4155         doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
4156 
4157         assertEquals(mockPhone2,
4158                 mTestConnectionService.getPhoneInEmergencyCallbackMode());
4159     }
4160 
setupMockEmergencyNumbers(Phone mockPhone, List<EmergencyNumber> numbers)4161     private void setupMockEmergencyNumbers(Phone mockPhone, List<EmergencyNumber> numbers) {
4162         EmergencyNumberTracker emergencyNumberTracker = Mockito.mock(EmergencyNumberTracker.class);
4163         // Yuck.  There should really be a fake emergency number class which makes it easy to inject
4164         // the numbers for testing.
4165         ArrayMap<String, List<EmergencyNumber>> numbersMap = new ArrayMap<>();
4166         for (EmergencyNumber number : numbers) {
4167             when(emergencyNumberTracker.getEmergencyNumber(eq(number.getNumber())))
4168                     .thenReturn(number);
4169             if (!numbersMap.containsKey(number.getNumber())) {
4170                 numbersMap.put(number.getNumber(), new ArrayList<>());
4171             }
4172             numbersMap.get(number.getNumber()).add(number);
4173         }
4174         // Double yuck.
4175         for (Map.Entry<String, List<EmergencyNumber>> entry : numbersMap.entrySet()) {
4176             when(emergencyNumberTracker.getEmergencyNumbers(eq(entry.getKey()))).thenReturn(
4177                     entry.getValue());
4178         }
4179         when(mockPhone.getEmergencyNumberTracker()).thenReturn(emergencyNumberTracker);
4180     }
4181 
setupForDialForDomainSelection(Phone mockPhone, int domain, boolean isEmergency)4182     private void setupForDialForDomainSelection(Phone mockPhone, int domain, boolean isEmergency) {
4183         if (isEmergency) {
4184             doReturn(mEmergencyCallDomainSelectionConnection).when(mDomainSelectionResolver)
4185                     .getDomainSelectionConnection(any(), anyInt(), eq(true));
4186             doReturn(CompletableFuture.completedFuture(domain))
4187                     .when(mEmergencyCallDomainSelectionConnection)
4188                     .createEmergencyConnection(any(), any());
4189             doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
4190         } else {
4191             doReturn(mNormalCallDomainSelectionConnection).when(mDomainSelectionResolver)
4192                     .getDomainSelectionConnection(any(), eq(SELECTOR_TYPE_CALLING), eq(false));
4193             doReturn(CompletableFuture.completedFuture(domain))
4194                     .when(mNormalCallDomainSelectionConnection)
4195                     .createNormalConnection(any(), any());
4196             doReturn(false).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
4197         }
4198 
4199         doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
4200         doReturn(mImsPhone).when(mockPhone).getImsPhone();
4201     }
4202 
setupConnectionServiceInApmForDomainSelection(boolean normalRouting)4203     private Phone setupConnectionServiceInApmForDomainSelection(boolean normalRouting) {
4204         ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
4205                 .setAccountHandle(PHONE_ACCOUNT_HANDLE_1)
4206                 .setAddress(TEST_ADDRESS)
4207                 .build();
4208         Phone testPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_POWER_OFF,
4209                 false /*isEmergencyOnly*/);
4210         Phone testPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_POWER_OFF,
4211                 false /*isEmergencyOnly*/);
4212         doReturn(GSM_PHONE).when(testPhone0).getPhoneType();
4213         doReturn(GSM_PHONE).when(testPhone1).getPhoneType();
4214         List<Phone> phones = new ArrayList<>(2);
4215         doReturn(false).when(testPhone0).isRadioOn();
4216         doReturn(false).when(testPhone1).isRadioOn();
4217         phones.add(testPhone0);
4218         phones.add(testPhone1);
4219         setPhones(phones);
4220         setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_1, testPhone0);
4221         setupDeviceConfig(testPhone0, testPhone1, 0);
4222         setupForDialForDomainSelection(testPhone0, DOMAIN_CS, false);
4223 
4224         EmergencyNumber emergencyNumber;
4225         if (normalRouting) {
4226             emergencyNumber = new EmergencyNumber(TEST_ADDRESS.getSchemeSpecificPart(), "", "",
4227                     EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
4228                     Collections.emptyList(),
4229                     EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE,
4230                     EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
4231         } else {
4232             emergencyNumber = setupEmergencyNumber(TEST_ADDRESS);
4233         }
4234         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
4235         doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
4236         doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
4237                 anyString());
4238         doReturn(2).when(mTelephonyManagerProxy).getPhoneCount();
4239 
4240         mConnection = mTestConnectionService.onCreateOutgoingConnection(
4241                 PHONE_ACCOUNT_HANDLE_1, connectionRequest);
4242         assertNotNull("test connection was not set up correctly.", mConnection);
4243 
4244         return testPhone0;
4245     }
4246 
setupForReDialForDomainSelection( Phone mockPhone, int domain, int preciseDisconnectCause, int disconnectCause, boolean fromEmergency)4247     private TestTelephonyConnection setupForReDialForDomainSelection(
4248             Phone mockPhone, int domain, int preciseDisconnectCause,
4249             int disconnectCause, boolean fromEmergency) throws Exception {
4250         TestTelephonyConnection c = new TestTelephonyConnection();
4251         try {
4252             if (fromEmergency) {
4253                 doReturn(CompletableFuture.completedFuture(domain))
4254                         .when(mEmergencyCallDomainSelectionConnection)
4255                         .reselectDomain(any());
4256                 replaceInstance(TelephonyConnectionService.class,
4257                         "mEmergencyCallDomainSelectionConnection",
4258                         mTestConnectionService, mEmergencyCallDomainSelectionConnection);
4259                 replaceInstance(TelephonyConnectionService.class, "mEmergencyConnection",
4260                         mTestConnectionService, c);
4261             } else {
4262                 doReturn(CompletableFuture.completedFuture(domain))
4263                         .when(mNormalCallDomainSelectionConnection).reselectDomain(any());
4264                 replaceInstance(TelephonyConnectionService.class, "mDomainSelectionConnection",
4265                         mTestConnectionService, mNormalCallDomainSelectionConnection);
4266             }
4267         } catch (Exception e) {
4268             // This shouldn't happen
4269             fail();
4270         }
4271 
4272         doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
4273 
4274         c.setTelecomCallId(TELECOM_CALL_ID1);
4275         c.setMockPhone(mockPhone);
4276         c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
4277 
4278         Connection oc = c.getOriginalConnection();
4279         doReturn(disconnectCause).when(oc).getDisconnectCause();
4280         doReturn(preciseDisconnectCause).when(oc).getPreciseDisconnectCause();
4281 
4282         return c;
4283     }
4284 
createTestConnection(PhoneAccountHandle handle, int properties, boolean isEmergency)4285     private SimpleTelephonyConnection createTestConnection(PhoneAccountHandle handle,
4286             int properties, boolean isEmergency) {
4287         SimpleTelephonyConnection connection = new SimpleTelephonyConnection();
4288         connection.setShouldTreatAsEmergencyCall(isEmergency);
4289         connection.setConnectionProperties(properties);
4290         connection.setPhoneAccountHandle(handle);
4291         return connection;
4292     }
4293 
createTestConference(PhoneAccountHandle handle, int properties)4294     private SimpleConference createTestConference(PhoneAccountHandle handle, int properties) {
4295         SimpleConference conference = new SimpleConference(handle);
4296         conference.setConnectionProperties(properties);
4297         return conference;
4298     }
4299 
4300     /**
4301      * Setup the mess of mocks for {@link #testSecondCallSameSubWontDisconnect()} and
4302      * {@link #testIncomingDoesntRequestDisconnect()}.
4303      */
setupForCallTest()4304     private void setupForCallTest() {
4305         // Setup a bunch of stuff.  Blech.
4306         mTestConnectionService.setReadyForTest();
4307         mPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_IN_SERVICE,
4308                 false /*isEmergencyOnly*/);
4309         when(mCall.getState()).thenReturn(Call.State.INCOMING);
4310         when(mCall.getPhone()).thenReturn(mPhone0);
4311         when(mPhone0.getRingingCall()).thenReturn(mCall);
4312         mPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_IN_SERVICE,
4313                 false /*isEmergencyOnly*/);
4314         when(mCall2.getPhone()).thenReturn(mPhone1);
4315         List<Phone> phones = new ArrayList<>(2);
4316         doReturn(true).when(mPhone0).isRadioOn();
4317         doReturn(true).when(mPhone1).isRadioOn();
4318         doReturn(GSM_PHONE).when(mPhone0).getPhoneType();
4319         doReturn(GSM_PHONE).when(mPhone1).getPhoneType();
4320         phones.add(mPhone0);
4321         phones.add(mPhone1);
4322         setPhones(phones);
4323         when(mPhoneUtilsProxy.getSubIdForPhoneAccountHandle(eq(PHONE_ACCOUNT_HANDLE_1)))
4324                 .thenReturn(0);
4325         when(mSubscriptionManagerProxy.getPhoneId(0)).thenReturn(0);
4326         when(mPhoneFactoryProxy.getPhone(eq(0))).thenReturn(mPhone0);
4327         when(mPhoneUtilsProxy.getSubIdForPhoneAccountHandle(eq(PHONE_ACCOUNT_HANDLE_2)))
4328                 .thenReturn(1);
4329         when(mSubscriptionManagerProxy.getPhoneId(1)).thenReturn(1);
4330         when(mPhoneFactoryProxy.getPhone(eq(1))).thenReturn(mPhone1);
4331         setupDeviceConfig(mPhone0, mPhone1, 1);
4332 
4333         when(mInternalConnection.getCall()).thenReturn(mCall);
4334         when(mInternalConnection.getState()).thenReturn(Call.State.ACTIVE);
4335         when(mInternalConnection2.getCall()).thenReturn(mCall2);
4336         when(mInternalConnection2.getState()).thenReturn(Call.State.WAITING);
4337     }
4338 
4339     /**
4340      * Set up a mock MSIM device with TEST_ADDRESS set as an emergency number.
4341      * @param isRoaming whether it is roaming
4342      * @param setOperatorName whether operator name needs to set
4343      * @param operatorNameLongName the operator long name if needs to set
4344      * @param operatorNameShortName the operator short name if needs to set
4345      * @param operatorNameNumeric the operator numeric name if needs to set
4346      * @return the Phone associated with slot 0.
4347      */
setupConnectionServiceForDelayDial(boolean isRoaming, boolean setOperatorName, String operatorNameLongName, String operatorNameShortName, String operatorNameNumeric)4348     private Phone setupConnectionServiceForDelayDial(boolean isRoaming, boolean setOperatorName,
4349             String operatorNameLongName, String operatorNameShortName,
4350                     String operatorNameNumeric) {
4351         ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
4352                 .setAccountHandle(PHONE_ACCOUNT_HANDLE_1)
4353                 .setAddress(TEST_ADDRESS)
4354                 .build();
4355         Phone testPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_IN_SERVICE,
4356                 false /*isEmergencyOnly*/);
4357         Phone testPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_OUT_OF_SERVICE,
4358                 false /*isEmergencyOnly*/);
4359         List<Phone> phones = new ArrayList<>(2);
4360         doReturn(true).when(testPhone0).isRadioOn();
4361         doReturn(true).when(testPhone1).isRadioOn();
4362         phones.add(testPhone0);
4363         phones.add(testPhone1);
4364         setPhones(phones);
4365         setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_1, testPhone0);
4366         setupDeviceConfig(testPhone0, testPhone1, 1);
4367         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(
4368                 TEST_ADDRESS.getSchemeSpecificPart());
4369         HashMap<Integer, List<EmergencyNumber>> emergencyNumbers = new HashMap<>(1);
4370         List<EmergencyNumber> numbers = new ArrayList<>();
4371         numbers.add(setupEmergencyNumber(TEST_ADDRESS));
4372         emergencyNumbers.put(0 /*subId*/, numbers);
4373         doReturn(emergencyNumbers).when(mTelephonyManagerProxy).getCurrentEmergencyNumberList();
4374         doReturn(2).when(mTelephonyManagerProxy).getPhoneCount();
4375         testPhone0.getServiceState().setRoaming(isRoaming);
4376         if (setOperatorName) {
4377             testPhone0.getServiceState().setOperatorName(operatorNameLongName,
4378                     operatorNameShortName, operatorNameNumeric);
4379         }
4380         mConnection = mTestConnectionService.onCreateOutgoingConnection(
4381                 PHONE_ACCOUNT_HANDLE_1, connectionRequest);
4382         assertNotNull("test connection was not set up correctly.", mConnection);
4383         return testPhone0;
4384     }
4385 
4386     /**
4387      * Set up a mock MSIM device with TEST_ADDRESS set as an emergency number in airplane mode.
4388      * @return the Phone associated with slot 0.
4389      */
setupConnectionServiceInApm()4390     private Phone setupConnectionServiceInApm() {
4391         ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
4392                 .setAccountHandle(PHONE_ACCOUNT_HANDLE_1)
4393                 .setAddress(TEST_ADDRESS)
4394                 .build();
4395         Phone testPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_POWER_OFF,
4396                 false /*isEmergencyOnly*/);
4397         Phone testPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_POWER_OFF,
4398                 false /*isEmergencyOnly*/);
4399         doReturn(GSM_PHONE).when(testPhone0).getPhoneType();
4400         doReturn(GSM_PHONE).when(testPhone1).getPhoneType();
4401         List<Phone> phones = new ArrayList<>(2);
4402         doReturn(false).when(testPhone0).isRadioOn();
4403         doReturn(false).when(testPhone1).isRadioOn();
4404         phones.add(testPhone0);
4405         phones.add(testPhone1);
4406         setPhones(phones);
4407         setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_1, testPhone0);
4408         setupDeviceConfig(testPhone0, testPhone1, 0);
4409         doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(
4410                 TEST_ADDRESS.getSchemeSpecificPart());
4411         HashMap<Integer, List<EmergencyNumber>> emergencyNumbers = new HashMap<>(1);
4412         List<EmergencyNumber> numbers = new ArrayList<>();
4413         numbers.add(setupEmergencyNumber(TEST_ADDRESS));
4414         emergencyNumbers.put(0 /*subId*/, numbers);
4415         doReturn(emergencyNumbers).when(mTelephonyManagerProxy).getCurrentEmergencyNumberList();
4416         doReturn(2).when(mTelephonyManagerProxy).getPhoneCount();
4417 
4418         mConnection = mTestConnectionService.onCreateOutgoingConnection(
4419                 PHONE_ACCOUNT_HANDLE_1, connectionRequest);
4420         assertNotNull("test connection was not set up correctly.", mConnection);
4421 
4422         return testPhone0;
4423     }
4424 
setupEmergencyNumber(Uri address)4425     private EmergencyNumber setupEmergencyNumber(Uri address) {
4426         return new EmergencyNumber(address.getSchemeSpecificPart(), "", "",
4427         EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
4428         Collections.emptyList(),
4429         EmergencyNumber.EMERGENCY_NUMBER_SOURCE_SIM,
4430         EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY);
4431     }
4432 
setupHandleToPhoneMap(PhoneAccountHandle handle, Phone phone)4433     private void setupHandleToPhoneMap(PhoneAccountHandle handle, Phone phone) {
4434         // The specified handle has an id which is subID
4435         doReturn(Integer.parseInt(handle.getId())).when(mPhoneUtilsProxy)
4436                 .getSubIdForPhoneAccountHandle(eq(handle));
4437         // The specified sub id in the passed handle will correspond to the phone's phone id.
4438         doReturn(phone.getPhoneId()).when(mSubscriptionManagerProxy)
4439                 .getPhoneId(eq(Integer.parseInt(handle.getId())));
4440         int phoneId = phone.getPhoneId();
4441         doReturn(phone).when(mPhoneFactoryProxy).getPhone(eq(phoneId));
4442     }
4443 
getSuppServiceNotification(int notificationType, int code)4444     private AsyncResult getSuppServiceNotification(int notificationType, int code) {
4445         SuppServiceNotification notification = new SuppServiceNotification();
4446         notification.notificationType = notificationType;
4447         notification.code = code;
4448         return new AsyncResult(null, notification, null);
4449     }
4450 
makeTestPhone(int phoneId, int serviceState, boolean isEmergencyOnly)4451     private Phone makeTestPhone(int phoneId, int serviceState, boolean isEmergencyOnly) {
4452         Phone phone = mock(Phone.class);
4453         ServiceState testServiceState = new ServiceState();
4454         testServiceState.setState(serviceState);
4455         testServiceState.setEmergencyOnly(isEmergencyOnly);
4456         when(phone.getContext()).thenReturn(mContext);
4457         when(phone.getServiceState()).thenReturn(testServiceState);
4458         when(phone.getPhoneId()).thenReturn(phoneId);
4459         when(phone.getDefaultPhone()).thenReturn(phone);
4460         when(phone.getEmergencyNumberTracker()).thenReturn(mEmergencyNumberTracker);
4461         when(phone.getServiceStateTracker()).thenReturn(mSST);
4462         doNothing().when(phone).registerForPreciseCallStateChanged(any(Handler.class), anyInt(),
4463                 any(Object.class));
4464         when(mEmergencyNumberTracker.getEmergencyNumber(anyString())).thenReturn(null);
4465         return phone;
4466     }
4467 
4468     // Setup 2 SIM device
setupDeviceConfig(Phone slot0Phone, Phone slot1Phone, int defaultVoicePhoneId)4469     private void setupDeviceConfig(Phone slot0Phone, Phone slot1Phone, int defaultVoicePhoneId) {
4470         when(mTelephonyManagerProxy.getPhoneCount()).thenReturn(2);
4471         when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(false);
4472         when(mSubscriptionManagerProxy.getDefaultVoicePhoneId()).thenReturn(defaultVoicePhoneId);
4473         when(mPhoneFactoryProxy.getPhone(eq(SLOT_0_PHONE_ID))).thenReturn(slot0Phone);
4474         when(mPhoneFactoryProxy.getPhone(eq(SLOT_1_PHONE_ID))).thenReturn(slot1Phone);
4475     }
4476 
setDefaultDataPhoneId(int defaultDataPhoneId)4477     private void setDefaultDataPhoneId(int defaultDataPhoneId) {
4478         when(mSubscriptionManagerProxy.getDefaultDataPhoneId()).thenReturn(defaultDataPhoneId);
4479     }
4480 
setPhoneRadioAccessFamily(Phone phone, int radioAccessFamily)4481     private void setPhoneRadioAccessFamily(Phone phone, int radioAccessFamily) {
4482         when(phone.getRadioAccessFamily()).thenReturn(radioAccessFamily);
4483     }
4484 
setEmergencySmsMode(Phone phone, boolean isInEmergencySmsMode)4485     private void setEmergencySmsMode(Phone phone, boolean isInEmergencySmsMode) {
4486         when(phone.isInEmergencySmsMode()).thenReturn(isInEmergencySmsMode);
4487     }
4488 
setPhoneSlotState(int slotId, int slotState)4489     private void setPhoneSlotState(int slotId, int slotState) {
4490         when(mSubscriptionManagerProxy.getSimStateForSlotIdx(slotId)).thenReturn(slotState);
4491     }
4492 
setDefaultPhone(Phone phone)4493     private void setDefaultPhone(Phone phone) {
4494         when(mPhoneFactoryProxy.getDefaultPhone()).thenReturn(phone);
4495     }
4496 
setPhones(List<Phone> phones)4497     private void setPhones(List<Phone> phones) {
4498         when(mPhoneFactoryProxy.getPhones()).thenReturn(phones.toArray(new Phone[phones.size()]));
4499         when(mPhoneFactoryProxy.getDefaultPhone()).thenReturn(phones.get(0));
4500     }
4501 
setPhonesDialConnection(Phone phone, Connection c)4502     private void setPhonesDialConnection(Phone phone, Connection c) {
4503         try {
4504             when(phone.dial(anyString(), any(), any())).thenReturn(c);
4505         } catch (CallStateException e) {
4506             // this shouldn't happen
4507             fail();
4508         }
4509     }
4510 
createConnectionRequest( PhoneAccountHandle accountHandle, String address, String callId)4511     private ConnectionRequest createConnectionRequest(
4512             PhoneAccountHandle accountHandle, String address, String callId) {
4513         return new ConnectionRequest.Builder()
4514                 .setAccountHandle(accountHandle)
4515                 .setAddress(Uri.parse("tel:" + address))
4516                 .setExtras(new Bundle())
4517                 .setTelecomCallId(callId)
4518                 .build();
4519     }
4520 
getExecutor()4521     private Executor getExecutor() {
4522         return Runnable::run;
4523     }
4524 }
4525