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 com.android.internal.telephony.RILConstants.GSM_PHONE; 20 21 import static junit.framework.Assert.assertEquals; 22 import static junit.framework.Assert.assertFalse; 23 import static junit.framework.Assert.assertNotNull; 24 import static junit.framework.Assert.assertTrue; 25 import static junit.framework.Assert.fail; 26 27 import static org.mockito.ArgumentMatchers.any; 28 import static org.mockito.ArgumentMatchers.anyInt; 29 import static org.mockito.ArgumentMatchers.anyString; 30 import static org.mockito.Matchers.eq; 31 import static org.mockito.Mockito.doAnswer; 32 import static org.mockito.Mockito.doNothing; 33 import static org.mockito.Mockito.doReturn; 34 import static org.mockito.Mockito.mock; 35 import static org.mockito.Mockito.never; 36 import static org.mockito.Mockito.verify; 37 import static org.mockito.Mockito.when; 38 39 import android.content.ComponentName; 40 import android.content.Context; 41 import android.net.Uri; 42 import android.os.AsyncResult; 43 import android.os.Bundle; 44 import android.os.Handler; 45 import android.telecom.ConnectionRequest; 46 import android.telecom.DisconnectCause; 47 import android.telecom.PhoneAccountHandle; 48 import android.telecom.TelecomManager; 49 import android.telephony.CarrierConfigManager; 50 import android.telephony.RadioAccessFamily; 51 import android.telephony.ServiceState; 52 import android.telephony.TelephonyManager; 53 import android.telephony.emergency.EmergencyNumber; 54 import android.test.suitebuilder.annotation.SmallTest; 55 56 import androidx.test.runner.AndroidJUnit4; 57 58 import com.android.TelephonyTestBase; 59 import com.android.internal.telecom.IConnectionService; 60 import com.android.internal.telephony.Call; 61 import com.android.internal.telephony.CallStateException; 62 import com.android.internal.telephony.Connection; 63 import com.android.internal.telephony.Phone; 64 import com.android.internal.telephony.PhoneSwitcher; 65 import com.android.internal.telephony.ServiceStateTracker; 66 import com.android.internal.telephony.emergency.EmergencyNumberTracker; 67 import com.android.internal.telephony.gsm.SuppServiceNotification; 68 69 import org.junit.After; 70 import org.junit.Before; 71 import org.junit.Test; 72 import org.junit.runner.RunWith; 73 import org.mockito.ArgumentCaptor; 74 import org.mockito.Mock; 75 76 import java.util.ArrayList; 77 import java.util.Collections; 78 import java.util.HashMap; 79 import java.util.List; 80 81 /** 82 * Unit tests for TelephonyConnectionService. 83 */ 84 85 @RunWith(AndroidJUnit4.class) 86 public class TelephonyConnectionServiceTest extends TelephonyTestBase { 87 /** 88 * Unlike {@link TestTelephonyConnection}, a bare minimal {@link TelephonyConnection} impl 89 * that does not try to configure anything. 90 */ 91 public static class SimpleTelephonyConnection extends TelephonyConnection { 92 public boolean wasDisconnected = false; 93 94 @Override cloneConnection()95 public TelephonyConnection cloneConnection() { 96 return null; 97 } 98 99 @Override hangup(int telephonyDisconnectCode)100 public void hangup(int telephonyDisconnectCode) { 101 wasDisconnected = true; 102 } 103 } 104 105 private static final long TIMEOUT_MS = 100; 106 private static final int SLOT_0_PHONE_ID = 0; 107 private static final int SLOT_1_PHONE_ID = 1; 108 109 private static final ComponentName TEST_COMPONENT_NAME = new ComponentName( 110 "com.android.phone.tests", TelephonyConnectionServiceTest.class.getName()); 111 private static final String TEST_ACCOUNT_ID1 = "id1"; 112 private static final String TEST_ACCOUNT_ID2 = "id2"; 113 private static final PhoneAccountHandle PHONE_ACCOUNT_HANDLE_1 = new PhoneAccountHandle( 114 TEST_COMPONENT_NAME, TEST_ACCOUNT_ID1); 115 private static final PhoneAccountHandle PHONE_ACCOUNT_HANDLE_2 = new PhoneAccountHandle( 116 TEST_COMPONENT_NAME, TEST_ACCOUNT_ID2); 117 private static final Uri TEST_ADDRESS = Uri.parse("tel:+16505551212"); 118 private android.telecom.Connection mConnection; 119 120 @Mock TelephonyConnectionService.TelephonyManagerProxy mTelephonyManagerProxy; 121 @Mock TelephonyConnectionService.SubscriptionManagerProxy mSubscriptionManagerProxy; 122 @Mock TelephonyConnectionService.PhoneFactoryProxy mPhoneFactoryProxy; 123 @Mock DeviceState mDeviceState; 124 @Mock TelephonyConnectionService.PhoneSwitcherProxy mPhoneSwitcherProxy; 125 @Mock TelephonyConnectionService.PhoneNumberUtilsProxy mPhoneNumberUtilsProxy; 126 @Mock TelephonyConnectionService.PhoneUtilsProxy mPhoneUtilsProxy; 127 @Mock TelephonyConnectionService.DisconnectCauseFactory mDisconnectCauseFactory; 128 @Mock Handler mMockHandler; 129 @Mock EmergencyNumberTracker mEmergencyNumberTracker; 130 @Mock PhoneSwitcher mPhoneSwitcher; 131 @Mock RadioOnHelper mRadioOnHelper; 132 @Mock ServiceStateTracker mSST; 133 @Mock Call mCall; 134 @Mock Call mCall2; 135 @Mock com.android.internal.telephony.Connection mInternalConnection; 136 @Mock com.android.internal.telephony.Connection mInternalConnection2; 137 private Phone mPhone0; 138 private Phone mPhone1; 139 140 private static class TestTelephonyConnectionService extends TelephonyConnectionService { 141 142 private final Context mContext; 143 TestTelephonyConnectionService(Context context)144 TestTelephonyConnectionService(Context context) { 145 mContext = context; 146 } 147 148 @Override onCreate()149 public void onCreate() { 150 // attach test context. 151 attachBaseContext(mContext); 152 super.onCreate(); 153 } 154 } 155 156 private TelephonyConnectionService mTestConnectionService; 157 private IConnectionService.Stub mBinderStub; 158 159 @Before setUp()160 public void setUp() throws Exception { 161 super.setUp(); 162 mTestConnectionService = new TestTelephonyConnectionService(mContext); 163 mTestConnectionService.setPhoneFactoryProxy(mPhoneFactoryProxy); 164 mTestConnectionService.setSubscriptionManagerProxy(mSubscriptionManagerProxy); 165 // Set configurations statically 166 doReturn(false).when(mDeviceState).shouldCheckSimStateBeforeOutgoingCall(any()); 167 mTestConnectionService.setPhoneSwitcherProxy(mPhoneSwitcherProxy); 168 doReturn(mPhoneSwitcher).when(mPhoneSwitcherProxy).getPhoneSwitcher(); 169 when(mPhoneNumberUtilsProxy.convertToEmergencyNumber(any(), anyString())) 170 .thenAnswer(invocation -> invocation.getArgument(1)); 171 mTestConnectionService.setPhoneNumberUtilsProxy(mPhoneNumberUtilsProxy); 172 mTestConnectionService.setPhoneUtilsProxy(mPhoneUtilsProxy); 173 mTestConnectionService.setDeviceState(mDeviceState); 174 mTestConnectionService.setRadioOnHelper(mRadioOnHelper); 175 doReturn(new DisconnectCause(DisconnectCause.UNKNOWN)).when(mDisconnectCauseFactory) 176 .toTelecomDisconnectCause(anyInt(), any()); 177 doReturn(new DisconnectCause(DisconnectCause.UNKNOWN)).when(mDisconnectCauseFactory) 178 .toTelecomDisconnectCause(anyInt(), any(), anyInt()); 179 mTestConnectionService.setDisconnectCauseFactory(mDisconnectCauseFactory); 180 mTestConnectionService.onCreate(); 181 mTestConnectionService.setTelephonyManagerProxy(mTelephonyManagerProxy); 182 mBinderStub = (IConnectionService.Stub) mTestConnectionService.onBind(null); 183 } 184 185 @After tearDown()186 public void tearDown() throws Exception { 187 mTestConnectionService = null; 188 super.tearDown(); 189 } 190 191 /** 192 * Prerequisites: 193 * - MSIM Device, two slots with SIMs inserted 194 * - Users default Voice SIM choice is IN_SERVICE 195 * 196 * Result: getFirstPhoneForEmergencyCall returns the default Voice SIM choice. 197 */ 198 @Test 199 @SmallTest testDefaultVoiceSimInService()200 public void testDefaultVoiceSimInService() { 201 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_IN_SERVICE, 202 false /*isEmergencyOnly*/); 203 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 204 true /*isEmergencyOnly*/); 205 setDefaultPhone(slot0Phone); 206 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 207 208 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 209 210 assertEquals(slot0Phone, resultPhone); 211 } 212 213 /** 214 * Prerequisites: 215 * - MSIM Device, two slots with SIMs inserted 216 * - Slot 0 is OUT_OF_SERVICE, Slot 1 is OUT_OF_SERVICE (emergency calls only) 217 * 218 * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone 219 */ 220 @Test 221 @SmallTest testSlot1EmergencyOnly()222 public void testSlot1EmergencyOnly() { 223 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 224 false /*isEmergencyOnly*/); 225 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 226 true /*isEmergencyOnly*/); 227 setDefaultPhone(slot0Phone); 228 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 229 230 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 231 232 assertEquals(slot1Phone, resultPhone); 233 } 234 235 /** 236 * Prerequisites: 237 * - MSIM Device, two slots with SIMs inserted 238 * - Slot 0 is OUT_OF_SERVICE, Slot 1 is IN_SERVICE 239 * 240 * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone 241 */ 242 @Test 243 @SmallTest testSlot1InService()244 public void testSlot1InService() { 245 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 246 false /*isEmergencyOnly*/); 247 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_IN_SERVICE, 248 false /*isEmergencyOnly*/); 249 setDefaultPhone(slot0Phone); 250 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 251 252 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 253 254 assertEquals(slot1Phone, resultPhone); 255 } 256 257 /** 258 * Prerequisites: 259 * - MSIM Device, two slots with SIMs inserted 260 * - Slot 0 is PUK locked, Slot 1 is ready 261 * - Slot 0 is LTE capable, Slot 1 is GSM capable 262 * 263 * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone. Although Slot 0 is more 264 * capable, it is locked, so use the other slot. 265 */ 266 @Test 267 @SmallTest testSlot0PukLocked()268 public void testSlot0PukLocked() { 269 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 270 false /*isEmergencyOnly*/); 271 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 272 false /*isEmergencyOnly*/); 273 setDefaultPhone(slot0Phone); 274 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 275 // Set Slot 0 to be PUK locked 276 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_PUK_REQUIRED); 277 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY); 278 // Make Slot 0 higher capability 279 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE); 280 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_GSM); 281 282 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 283 284 assertEquals(slot1Phone, resultPhone); 285 } 286 287 /** 288 * Prerequisites: 289 * - MSIM Device, two slots with SIMs inserted 290 * - Slot 0 is PIN locked, Slot 1 is ready 291 * - Slot 0 is LTE capable, Slot 1 is GSM capable 292 * 293 * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone. Although Slot 0 is more 294 * capable, it is locked, so use the other slot. 295 */ 296 @Test 297 @SmallTest testSlot0PinLocked()298 public void testSlot0PinLocked() { 299 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 300 false /*isEmergencyOnly*/); 301 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 302 false /*isEmergencyOnly*/); 303 setDefaultPhone(slot0Phone); 304 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 305 // Set Slot 0 to be PUK locked 306 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_PIN_REQUIRED); 307 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY); 308 // Make Slot 0 higher capability 309 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE); 310 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_GSM); 311 312 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 313 314 assertEquals(slot1Phone, resultPhone); 315 } 316 317 /** 318 * Prerequisites: 319 * - MSIM Device, two slots with SIMs inserted 320 * - Slot 1 is PUK locked, Slot 0 is ready 321 * - Slot 1 is LTE capable, Slot 0 is GSM capable 322 * 323 * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone. Although Slot 1 is more 324 * capable, it is locked, so use the other slot. 325 */ 326 @Test 327 @SmallTest testSlot1PukLocked()328 public void testSlot1PukLocked() { 329 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 330 false /*isEmergencyOnly*/); 331 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 332 false /*isEmergencyOnly*/); 333 setDefaultPhone(slot0Phone); 334 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 335 // Set Slot 1 to be PUK locked 336 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY); 337 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_PUK_REQUIRED); 338 // Make Slot 1 higher capability 339 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM); 340 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE); 341 342 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 343 344 assertEquals(slot0Phone, resultPhone); 345 } 346 347 /** 348 * Prerequisites: 349 * - MSIM Device, two slots with SIMs inserted 350 * - Slot 1 is PIN locked, Slot 0 is ready 351 * - Slot 1 is LTE capable, Slot 0 is GSM capable 352 * 353 * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone. Although Slot 1 is more 354 * capable, it is locked, so use the other slot. 355 */ 356 @Test 357 @SmallTest testSlot1PinLocked()358 public void testSlot1PinLocked() { 359 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 360 false /*isEmergencyOnly*/); 361 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 362 false /*isEmergencyOnly*/); 363 setDefaultPhone(slot0Phone); 364 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 365 // Set Slot 1 to be PUK locked 366 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY); 367 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_PIN_REQUIRED); 368 // Make Slot 1 higher capability 369 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM); 370 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE); 371 372 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 373 374 assertEquals(slot0Phone, resultPhone); 375 } 376 377 /** 378 * Prerequisites: 379 * - MSIM Device, only slot 1 inserted and PUK locked 380 * - slot 1 has higher capabilities 381 * 382 * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it is the only one 383 * with a SIM inserted (even if it is PUK locked) 384 */ 385 @Test 386 @SmallTest testSlot1PinLockedAndSlot0Absent()387 public void testSlot1PinLockedAndSlot0Absent() { 388 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 389 false /*isEmergencyOnly*/); 390 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 391 false /*isEmergencyOnly*/); 392 setDefaultPhone(slot0Phone); 393 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 394 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT); 395 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_PIN_REQUIRED); 396 // Slot 1 has more capabilities 397 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM); 398 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE); 399 // Slot 1 has SIM inserted. 400 setSlotHasIccCard(SLOT_0_PHONE_ID, false /*isInserted*/); 401 setSlotHasIccCard(SLOT_1_PHONE_ID, true /*isInserted*/); 402 403 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 404 405 assertEquals(slot1Phone, resultPhone); 406 } 407 408 /** 409 * Prerequisites: 410 * - MSIM Device, two slots with SIMs inserted 411 * - Slot 1 is LTE capable, Slot 0 is GSM capable 412 * 413 * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it is more capable 414 */ 415 @Test 416 @SmallTest testSlot1HigherCapablity()417 public void testSlot1HigherCapablity() { 418 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 419 false /*isEmergencyOnly*/); 420 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 421 false /*isEmergencyOnly*/); 422 setDefaultPhone(slot0Phone); 423 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 424 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY); 425 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY); 426 // Make Slot 1 higher capability 427 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM); 428 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE); 429 430 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 431 432 assertEquals(slot1Phone, resultPhone); 433 } 434 435 /** 436 * Prerequisites: 437 * - MSIM Device, two slots with SIMs inserted 438 * - Slot 1 is GSM/LTE capable, Slot 0 is GSM capable 439 * 440 * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it has more 441 * capabilities. 442 */ 443 @Test 444 @SmallTest testSlot1MoreCapabilities()445 public void testSlot1MoreCapabilities() { 446 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 447 false /*isEmergencyOnly*/); 448 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 449 false /*isEmergencyOnly*/); 450 setDefaultPhone(slot0Phone); 451 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 452 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY); 453 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY); 454 // Make Slot 1 more capable 455 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE); 456 setPhoneRadioAccessFamily(slot1Phone, 457 RadioAccessFamily.RAF_GSM | RadioAccessFamily.RAF_LTE); 458 459 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 460 461 assertEquals(slot1Phone, resultPhone); 462 } 463 464 /** 465 * Prerequisites: 466 * - MSIM Device, two slots with SIMs inserted 467 * - Both SIMs PUK Locked 468 * - Slot 0 is LTE capable, Slot 1 is GSM capable 469 * 470 * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone because it is more capable, 471 * ignoring that both SIMs are PUK locked. 472 */ 473 @Test 474 @SmallTest testSlot0MoreCapableBothPukLocked()475 public void testSlot0MoreCapableBothPukLocked() { 476 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 477 false /*isEmergencyOnly*/); 478 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 479 false /*isEmergencyOnly*/); 480 setDefaultPhone(slot0Phone); 481 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 482 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_PUK_REQUIRED); 483 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_PUK_REQUIRED); 484 // Make Slot 0 higher capability 485 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE); 486 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_GSM); 487 488 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 489 490 assertEquals(slot0Phone, resultPhone); 491 } 492 493 /** 494 * Prerequisites: 495 * - MSIM Device, two slots with SIMs inserted 496 * - Both SIMs have the same capability 497 * 498 * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone because it is the first slot. 499 */ 500 @Test 501 @SmallTest testEqualCapabilityTwoSimsInserted()502 public void testEqualCapabilityTwoSimsInserted() { 503 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 504 false /*isEmergencyOnly*/); 505 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 506 false /*isEmergencyOnly*/); 507 setDefaultPhone(slot0Phone); 508 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 509 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY); 510 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY); 511 // Make Capability the same 512 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE); 513 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE); 514 // Two SIMs inserted 515 setSlotHasIccCard(SLOT_0_PHONE_ID, true /*isInserted*/); 516 setSlotHasIccCard(SLOT_1_PHONE_ID, true /*isInserted*/); 517 518 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 519 520 assertEquals(slot0Phone, resultPhone); 521 } 522 523 /** 524 * Prerequisites: 525 * - MSIM Device, only slot 0 inserted 526 * - Both SIMs have the same capability 527 * 528 * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone because it is the only one 529 * with a SIM inserted 530 */ 531 @Test 532 @SmallTest testEqualCapabilitySim0Inserted()533 public void testEqualCapabilitySim0Inserted() { 534 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 535 false /*isEmergencyOnly*/); 536 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 537 false /*isEmergencyOnly*/); 538 setDefaultPhone(slot0Phone); 539 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 540 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY); 541 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT); 542 // Make Capability the same 543 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE); 544 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE); 545 // Slot 0 has SIM inserted. 546 setSlotHasIccCard(SLOT_0_PHONE_ID, true /*isInserted*/); 547 setSlotHasIccCard(SLOT_1_PHONE_ID, false /*isInserted*/); 548 549 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 550 551 assertEquals(slot0Phone, resultPhone); 552 } 553 554 /** 555 * Prerequisites: 556 * - MSIM Device, only slot 1 inserted 557 * - Both SIMs have the same capability 558 * 559 * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it is the only one 560 * with a SIM inserted 561 */ 562 @Test 563 @SmallTest testEqualCapabilitySim1Inserted()564 public void testEqualCapabilitySim1Inserted() { 565 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 566 false /*isEmergencyOnly*/); 567 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 568 false /*isEmergencyOnly*/); 569 setDefaultPhone(slot0Phone); 570 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 571 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT); 572 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY); 573 // Make Capability the same 574 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE); 575 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE); 576 // Slot 1 has SIM inserted. 577 setSlotHasIccCard(SLOT_0_PHONE_ID, false /*isInserted*/); 578 setSlotHasIccCard(SLOT_1_PHONE_ID, true /*isInserted*/); 579 580 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 581 582 assertEquals(slot1Phone, resultPhone); 583 } 584 585 /** 586 * Prerequisites: 587 * - MSIM Device, no SIMs inserted 588 * - SIM 1 has the higher capability 589 * 590 * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone, since it is a higher 591 * capability 592 */ 593 @Test 594 @SmallTest testSim1HigherCapabilityNoSimsInserted()595 public void testSim1HigherCapabilityNoSimsInserted() { 596 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 597 false /*isEmergencyOnly*/); 598 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 599 false /*isEmergencyOnly*/); 600 setDefaultPhone(slot0Phone); 601 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 602 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT); 603 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT); 604 // Make Capability the same 605 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM); 606 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE); 607 // No SIMs inserted 608 setSlotHasIccCard(SLOT_0_PHONE_ID, false /*isInserted*/); 609 setSlotHasIccCard(SLOT_1_PHONE_ID, false /*isInserted*/); 610 611 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 612 613 assertEquals(slot1Phone, resultPhone); 614 } 615 616 /** 617 * Prerequisites: 618 * - MSIM Device, no SIMs inserted 619 * - Both SIMs have the same capability (Unknown) 620 * 621 * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone, since it is the first slot. 622 */ 623 @Test 624 @SmallTest testEqualCapabilityNoSimsInserted()625 public void testEqualCapabilityNoSimsInserted() { 626 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 627 false /*isEmergencyOnly*/); 628 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 629 false /*isEmergencyOnly*/); 630 setDefaultPhone(slot0Phone); 631 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 632 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT); 633 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT); 634 // Make Capability the same 635 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_UNKNOWN); 636 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_UNKNOWN); 637 // No SIMs inserted 638 setSlotHasIccCard(SLOT_0_PHONE_ID, false /*isInserted*/); 639 setSlotHasIccCard(SLOT_1_PHONE_ID, false /*isInserted*/); 640 641 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 642 643 assertEquals(slot0Phone, resultPhone); 644 } 645 646 /** 647 * The modem has returned a temporary error when placing an emergency call on a phone with one 648 * SIM slot. 649 * 650 * Verify that dial is called on the same phone again when retryOutgoingOriginalConnection is 651 * called. 652 */ 653 @Test 654 @SmallTest testRetryOutgoingOriginalConnection_redialTempFailOneSlot()655 public void testRetryOutgoingOriginalConnection_redialTempFailOneSlot() { 656 TestTelephonyConnection c = new TestTelephonyConnection(); 657 Phone slot0Phone = c.getPhone(); 658 when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID); 659 List<Phone> phones = new ArrayList<>(1); 660 phones.add(slot0Phone); 661 setPhones(phones); 662 c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED); 663 664 mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/); 665 666 // We never need to be notified in telecom that the PhoneAccount has changed, because it 667 // was redialed on the same slot 668 assertEquals(0, c.getNotifyPhoneAccountChangedCount()); 669 try { 670 verify(slot0Phone).dial(anyString(), any(), any()); 671 } catch (CallStateException e) { 672 // This shouldn't happen 673 fail(); 674 } 675 } 676 677 /** 678 * The modem has returned a permanent failure when placing an emergency call on a phone with one 679 * SIM slot. 680 * 681 * Verify that the connection is set to disconnected with an error disconnect cause and dial is 682 * not called. 683 */ 684 @Test 685 @SmallTest testRetryOutgoingOriginalConnection_redialPermFailOneSlot()686 public void testRetryOutgoingOriginalConnection_redialPermFailOneSlot() { 687 TestTelephonyConnection c = new TestTelephonyConnection(); 688 Phone slot0Phone = c.getPhone(); 689 when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID); 690 List<Phone> phones = new ArrayList<>(1); 691 phones.add(slot0Phone); 692 setPhones(phones); 693 c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED); 694 695 mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/); 696 697 // We never need to be notified in telecom that the PhoneAccount has changed, because it 698 // was never redialed 699 assertEquals(0, c.getNotifyPhoneAccountChangedCount()); 700 try { 701 verify(slot0Phone, never()).dial(anyString(), any(), any()); 702 } catch (CallStateException e) { 703 // This shouldn't happen 704 fail(); 705 } 706 assertEquals(c.getState(), android.telecom.Connection.STATE_DISCONNECTED); 707 assertEquals(c.getDisconnectCause().getCode(), DisconnectCause.ERROR); 708 } 709 710 /** 711 * The modem has returned a temporary failure when placing an emergency call on a phone with two 712 * SIM slots. 713 * 714 * Verify that the emergency call is dialed on the other slot and telecom is notified of the new 715 * PhoneAccount. 716 */ 717 @Test 718 @SmallTest testRetryOutgoingOriginalConnection_redialTempFailTwoSlot()719 public void testRetryOutgoingOriginalConnection_redialTempFailTwoSlot() { 720 TestTelephonyConnection c = new TestTelephonyConnection(); 721 Phone slot0Phone = c.getPhone(); 722 when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID); 723 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 724 false /*isEmergencyOnly*/); 725 setPhonesDialConnection(slot1Phone, c.getOriginalConnection()); 726 c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED); 727 List<Phone> phones = new ArrayList<>(2); 728 phones.add(slot0Phone); 729 phones.add(slot1Phone); 730 setPhones(phones); 731 doReturn(PHONE_ACCOUNT_HANDLE_1).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle( 732 slot0Phone); 733 doReturn(PHONE_ACCOUNT_HANDLE_2).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle( 734 slot1Phone); 735 736 mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/); 737 738 // The cache should still contain all of the Phones, since it was a temporary failure. 739 assertEquals(2, mTestConnectionService.mEmergencyRetryCache.second.size()); 740 // We need to be notified in Telecom that the PhoneAccount has changed, because it was 741 // redialed on another slot 742 assertEquals(1, c.getNotifyPhoneAccountChangedCount()); 743 try { 744 verify(slot1Phone).dial(anyString(), any(), any()); 745 } catch (CallStateException e) { 746 // This shouldn't happen 747 fail(); 748 } 749 } 750 751 /** 752 * The modem has returned a temporary failure when placing an emergency call on a phone with two 753 * SIM slots. 754 * 755 * Verify that the emergency call is dialed on the other slot and telecom is notified of the new 756 * PhoneAccount. 757 */ 758 @Test 759 @SmallTest testRetryOutgoingOriginalConnection_redialPermFailTwoSlot()760 public void testRetryOutgoingOriginalConnection_redialPermFailTwoSlot() { 761 TestTelephonyConnection c = new TestTelephonyConnection(); 762 Phone slot0Phone = c.getPhone(); 763 when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID); 764 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 765 false /*isEmergencyOnly*/); 766 setPhonesDialConnection(slot1Phone, c.getOriginalConnection()); 767 c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED); 768 List<Phone> phones = new ArrayList<>(2); 769 phones.add(slot0Phone); 770 phones.add(slot1Phone); 771 setPhones(phones); 772 doReturn(PHONE_ACCOUNT_HANDLE_1).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle( 773 slot0Phone); 774 doReturn(PHONE_ACCOUNT_HANDLE_2).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle( 775 slot1Phone); 776 777 mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/); 778 779 // The cache should only contain the slot1Phone. 780 assertEquals(1, mTestConnectionService.mEmergencyRetryCache.second.size()); 781 // We need to be notified in Telecom that the PhoneAccount has changed, because it was 782 // redialed on another slot 783 assertEquals(1, c.getNotifyPhoneAccountChangedCount()); 784 try { 785 verify(slot1Phone).dial(anyString(), any(), any()); 786 } catch (CallStateException e) { 787 // This shouldn't happen 788 fail(); 789 } 790 } 791 792 /** 793 * The modem has returned a temporary failure twice while placing an emergency call on a phone 794 * with two SIM slots. 795 * 796 * Verify that the emergency call is dialed on slot 1 and then on slot 0 and telecom is 797 * notified of this twice. 798 */ 799 @Test 800 @SmallTest testRetryOutgoingOriginalConnection_redialTempFailTwoSlot_twoFailure()801 public void testRetryOutgoingOriginalConnection_redialTempFailTwoSlot_twoFailure() { 802 TestTelephonyConnection c = new TestTelephonyConnection(); 803 Phone slot0Phone = c.getPhone(); 804 when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID); 805 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 806 false /*isEmergencyOnly*/); 807 setPhonesDialConnection(slot1Phone, c.getOriginalConnection()); 808 c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED); 809 List<Phone> phones = new ArrayList<>(2); 810 phones.add(slot0Phone); 811 phones.add(slot1Phone); 812 setPhones(phones); 813 doReturn(PHONE_ACCOUNT_HANDLE_1).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle( 814 slot0Phone); 815 doReturn(PHONE_ACCOUNT_HANDLE_2).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle( 816 slot1Phone); 817 818 // First Temporary failure 819 mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/); 820 // Set the Phone to the new phone that was just used to dial. 821 c.setMockPhone(slot1Phone); 822 // The cache should still contain all of the Phones, since it was a temporary failure. 823 assertEquals(2, mTestConnectionService.mEmergencyRetryCache.second.size()); 824 // Make sure slot 1 is next in the queue. 825 assertEquals(slot1Phone, mTestConnectionService.mEmergencyRetryCache.second.peek()); 826 // Second Temporary failure 827 mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/); 828 // Set the Phone to the new phone that was just used to dial. 829 c.setMockPhone(slot0Phone); 830 // The cache should still contain all of the Phones, since it was a temporary failure. 831 assertEquals(2, mTestConnectionService.mEmergencyRetryCache.second.size()); 832 // Make sure slot 0 is next in the queue. 833 assertEquals(slot0Phone, mTestConnectionService.mEmergencyRetryCache.second.peek()); 834 835 // We need to be notified in Telecom that the PhoneAccount has changed, because it was 836 // redialed on another slot 837 assertEquals(2, c.getNotifyPhoneAccountChangedCount()); 838 try { 839 verify(slot0Phone).dial(anyString(), any(), any()); 840 verify(slot1Phone).dial(anyString(), any(), any()); 841 } catch (CallStateException e) { 842 // This shouldn't happen 843 fail(); 844 } 845 } 846 847 /** 848 * The modem has returned a permanent failure twice while placing an emergency call on a phone 849 * with two SIM slots. 850 * 851 * Verify that the emergency call is dialed on slot 1 and then disconnected and telecom is 852 * notified of the change to slot 1. 853 */ 854 @Test 855 @SmallTest testRetryOutgoingOriginalConnection_redialPermFailTwoSlot_twoFailure()856 public void testRetryOutgoingOriginalConnection_redialPermFailTwoSlot_twoFailure() { 857 TestTelephonyConnection c = new TestTelephonyConnection(); 858 Phone slot0Phone = c.getPhone(); 859 when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID); 860 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 861 false /*isEmergencyOnly*/); 862 setPhonesDialConnection(slot1Phone, c.getOriginalConnection()); 863 c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED); 864 List<Phone> phones = new ArrayList<>(2); 865 phones.add(slot0Phone); 866 phones.add(slot1Phone); 867 setPhones(phones); 868 doReturn(PHONE_ACCOUNT_HANDLE_1).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle( 869 slot0Phone); 870 doReturn(PHONE_ACCOUNT_HANDLE_2).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle( 871 slot1Phone); 872 873 // First Permanent failure 874 mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/); 875 // Set the Phone to the new phone that was just used to dial. 876 c.setMockPhone(slot1Phone); 877 // The cache should only contain one phone 878 assertEquals(1, mTestConnectionService.mEmergencyRetryCache.second.size()); 879 // Make sure slot 1 is next in the queue. 880 assertEquals(slot1Phone, mTestConnectionService.mEmergencyRetryCache.second.peek()); 881 // Second Permanent failure 882 mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/); 883 // The cache should be empty 884 assertEquals(true, mTestConnectionService.mEmergencyRetryCache.second.isEmpty()); 885 886 assertEquals(c.getState(), android.telecom.Connection.STATE_DISCONNECTED); 887 assertEquals(c.getDisconnectCause().getCode(), DisconnectCause.ERROR); 888 // We need to be notified in Telecom that the PhoneAccount has changed, because it was 889 // redialed on another slot 890 assertEquals(1, c.getNotifyPhoneAccountChangedCount()); 891 try { 892 verify(slot1Phone).dial(anyString(), any(), any()); 893 verify(slot0Phone, never()).dial(anyString(), any(), any()); 894 } catch (CallStateException e) { 895 // This shouldn't happen 896 fail(); 897 } 898 } 899 900 @Test 901 @SmallTest testSuppServiceNotification()902 public void testSuppServiceNotification() { 903 TestTelephonyConnection c = new TestTelephonyConnection(); 904 905 // We need to set the original connection to cause the supp service notification 906 // registration to occur. 907 Phone phone = c.getPhone(); 908 c.setOriginalConnection(c.getOriginalConnection()); 909 doReturn(mContext).when(phone).getContext(); 910 911 // When the registration occurs, we'll capture the handler and message so we can post our 912 // own messages to it. 913 ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class); 914 ArgumentCaptor<Integer> messageCaptor = ArgumentCaptor.forClass(Integer.class); 915 verify(phone).registerForSuppServiceNotification(handlerCaptor.capture(), 916 messageCaptor.capture(), any()); 917 Handler handler = handlerCaptor.getValue(); 918 int message = messageCaptor.getValue(); 919 920 // With the handler and message now known, we'll post a supp service notification. 921 AsyncResult result = getSuppServiceNotification( 922 SuppServiceNotification.NOTIFICATION_TYPE_CODE_1, 923 SuppServiceNotification.CODE_1_CALL_FORWARDED); 924 handler.obtainMessage(message, result).sendToTarget(); 925 waitForHandlerAction(handler, TIMEOUT_MS); 926 927 assertTrue(c.getLastConnectionEvents().contains(TelephonyManager.EVENT_CALL_FORWARDED)); 928 929 // With the handler and message now known, we'll post a supp service notification. 930 result = getSuppServiceNotification( 931 SuppServiceNotification.NOTIFICATION_TYPE_CODE_1, 932 SuppServiceNotification.CODE_1_CALL_IS_WAITING); 933 handler.obtainMessage(message, result).sendToTarget(); 934 waitForHandlerAction(handler, TIMEOUT_MS); 935 936 // We we want the 3rd event since the forwarding one above sends 2. 937 assertEquals(c.getLastConnectionEvents().get(2), 938 TelephonyManager.EVENT_SUPPLEMENTARY_SERVICE_NOTIFICATION); 939 Bundle extras = c.getLastConnectionEventExtras().get(2); 940 assertEquals(SuppServiceNotification.NOTIFICATION_TYPE_CODE_1, 941 extras.getInt(TelephonyManager.EXTRA_NOTIFICATION_TYPE)); 942 assertEquals(SuppServiceNotification.CODE_1_CALL_IS_WAITING, 943 extras.getInt(TelephonyManager.EXTRA_NOTIFICATION_CODE)); 944 } 945 946 /** 947 * Test that the TelephonyConnectionService successfully performs a DDS switch before a call 948 * when we are not roaming and the carrier only supports SUPL over the data plane. 949 */ 950 @Test 951 @SmallTest testCreateOutgoingEmergencyConnection_delayDial_carrierconfig_dds()952 public void testCreateOutgoingEmergencyConnection_delayDial_carrierconfig_dds() { 953 // Setup test to not support SUPL on the non-DDS subscription 954 doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any()); 955 getTestContext().getCarrierConfig(0 /*subId*/).putStringArray( 956 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY, 957 null); 958 getTestContext().getCarrierConfig(0 /*subId*/).putInt( 959 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT, 960 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY); 961 getTestContext().getCarrierConfig(0 /*subId*/).putString( 962 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "150"); 963 964 Phone testPhone = setupConnectionServiceForDelayDial( 965 false /* isRoaming */, false /* setOperatorName */, null /* operator long name*/, 966 null /* operator short name */, null /* operator numeric name */); 967 verify(mPhoneSwitcher).overrideDefaultDataForEmergency(eq(0) /*phoneId*/ , 968 eq(150) /*extensionTime*/, any()); 969 } 970 971 /** 972 * Test that the TelephonyConnectionService successfully turns radio on before placing the 973 * emergency call. 974 */ 975 @Test 976 @SmallTest testCreateOutgoingEmerge_exitingApm_disconnected()977 public void testCreateOutgoingEmerge_exitingApm_disconnected() { 978 when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true); 979 Phone testPhone = setupConnectionServiceInApm(); 980 981 ArgumentCaptor<RadioOnStateListener.Callback> callback = 982 ArgumentCaptor.forClass(RadioOnStateListener.Callback.class); 983 verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), 984 eq(testPhone), eq(false)); 985 986 assertFalse(callback.getValue().isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE)); 987 when(mSST.isRadioOn()).thenReturn(true); 988 assertTrue(callback.getValue().isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE)); 989 990 mConnection.setDisconnected(null); 991 callback.getValue().onComplete(null, true); 992 for (Phone phone : mPhoneFactoryProxy.getPhones()) { 993 verify(phone).setRadioPower(true, false, false, true); 994 } 995 } 996 997 /** 998 * Test that the TelephonyConnectionService successfully turns radio on before placing the 999 * emergency call. 1000 */ 1001 @Test 1002 @SmallTest testCreateOutgoingEmergencyConnection_exitingApm_placeCall()1003 public void testCreateOutgoingEmergencyConnection_exitingApm_placeCall() { 1004 when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true); 1005 Phone testPhone = setupConnectionServiceInApm(); 1006 1007 ArgumentCaptor<RadioOnStateListener.Callback> callback = 1008 ArgumentCaptor.forClass(RadioOnStateListener.Callback.class); 1009 verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), 1010 eq(testPhone), eq(false)); 1011 1012 assertFalse(callback.getValue().isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE)); 1013 when(mSST.isRadioOn()).thenReturn(true); 1014 assertTrue(callback.getValue().isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE)); 1015 1016 callback.getValue().onComplete(null, true); 1017 1018 try { 1019 doAnswer(invocation -> null).when(mContext).startActivity(any()); 1020 verify(testPhone).dial(anyString(), any(), any()); 1021 } catch (CallStateException e) { 1022 // This shouldn't happen 1023 fail(); 1024 } 1025 } 1026 1027 /** 1028 * Test that the TelephonyConnectionService does not perform a DDS switch when the carrier 1029 * supports control-plane fallback. 1030 */ 1031 @Test 1032 @SmallTest testCreateOutgoingEmergencyConnection_delayDial_nocarrierconfig()1033 public void testCreateOutgoingEmergencyConnection_delayDial_nocarrierconfig() { 1034 // Setup test to not support SUPL on the non-DDS subscription 1035 doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any()); 1036 getTestContext().getCarrierConfig(0 /*subId*/).putStringArray( 1037 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY, 1038 null); 1039 getTestContext().getCarrierConfig(0 /*subId*/).putInt( 1040 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT, 1041 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK); 1042 getTestContext().getCarrierConfig(0 /*subId*/).putString( 1043 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0"); 1044 1045 Phone testPhone = setupConnectionServiceForDelayDial( 1046 false /* isRoaming */, false /* setOperatorName */, null /* operator long name*/, 1047 null /* operator short name */, null /* operator numeric name */); 1048 verify(mPhoneSwitcher, never()).overrideDefaultDataForEmergency(anyInt(), anyInt(), any()); 1049 } 1050 1051 /** 1052 * Test that the TelephonyConnectionService does not perform a DDS switch when the carrier 1053 * supports control-plane fallback. 1054 */ 1055 @Test 1056 @SmallTest testCreateOutgoingEmergencyConnection_delayDial_supportsuplondds()1057 public void testCreateOutgoingEmergencyConnection_delayDial_supportsuplondds() { 1058 // If the non-DDS supports SUPL, dont switch data 1059 doReturn(false).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any()); 1060 getTestContext().getCarrierConfig(0 /*subId*/).putStringArray( 1061 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY, 1062 null); 1063 getTestContext().getCarrierConfig(0 /*subId*/).putInt( 1064 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT, 1065 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY); 1066 getTestContext().getCarrierConfig(0 /*subId*/).putString( 1067 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0"); 1068 1069 Phone testPhone = setupConnectionServiceForDelayDial( 1070 false /* isRoaming */, false /* setOperatorName */, null /* operator long name*/, 1071 null /* operator short name */, null /* operator numeric name */); 1072 verify(mPhoneSwitcher, never()).overrideDefaultDataForEmergency(anyInt(), anyInt(), any()); 1073 } 1074 1075 /** 1076 * Test that the TelephonyConnectionService does not perform a DDS switch when the carrier does 1077 * not support control-plane fallback CarrierConfig while roaming. 1078 */ 1079 @Test 1080 @SmallTest testCreateOutgoingEmergencyConnection_delayDial_roaming_nocarrierconfig()1081 public void testCreateOutgoingEmergencyConnection_delayDial_roaming_nocarrierconfig() { 1082 // Setup test to not support SUPL on the non-DDS subscription 1083 doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any()); 1084 getTestContext().getCarrierConfig(0 /*subId*/).putStringArray( 1085 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY, 1086 null); 1087 getTestContext().getCarrierConfig(0 /*subId*/).putInt( 1088 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT, 1089 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY); 1090 getTestContext().getCarrierConfig(0 /*subId*/).putString( 1091 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0"); 1092 1093 Phone testPhone = setupConnectionServiceForDelayDial( 1094 true /* isRoaming */, false /* setOperatorName */, null /* operator long name*/, 1095 null /* operator short name */, null /* operator numeric name */); 1096 verify(mPhoneSwitcher, never()).overrideDefaultDataForEmergency(anyInt(), anyInt(), any()); 1097 } 1098 1099 /** 1100 * Test that the TelephonyConnectionService does perform a DDS switch even though the carrier 1101 * supports control-plane fallback CarrierConfig and the roaming partner is configured to look 1102 * like a home network. 1103 */ 1104 @Test 1105 @SmallTest testCreateOutgoingEmergencyConnection_delayDial_roamingcarrierconfig()1106 public void testCreateOutgoingEmergencyConnection_delayDial_roamingcarrierconfig() { 1107 doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any()); 1108 // Setup voice roaming scenario 1109 String testRoamingOperator = "001001"; 1110 // Setup test to not support SUPL on the non-DDS subscription 1111 String[] roamingPlmns = new String[1]; 1112 roamingPlmns[0] = testRoamingOperator; 1113 getTestContext().getCarrierConfig(0 /*subId*/).putStringArray( 1114 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY, 1115 roamingPlmns); 1116 getTestContext().getCarrierConfig(0 /*subId*/).putInt( 1117 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT, 1118 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK); 1119 getTestContext().getCarrierConfig(0 /*subId*/).putString( 1120 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0"); 1121 1122 Phone testPhone = setupConnectionServiceForDelayDial( 1123 false /* isRoaming */, true /* setOperatorName */, 1124 "TestTel" /* operator long name*/, "TestTel" /* operator short name */, 1125 testRoamingOperator /* operator numeric name */); 1126 verify(mPhoneSwitcher).overrideDefaultDataForEmergency(eq(0) /*phoneId*/ , 1127 eq(0) /*extensionTime*/, any()); 1128 } 1129 1130 /** 1131 * Test that the TelephonyConnectionService does perform a DDS switch even though the carrier 1132 * supports control-plane fallback CarrierConfig if we are roaming and the roaming partner is 1133 * configured to use data plane only SUPL. 1134 */ 1135 @Test 1136 @SmallTest testCreateOutgoingEmergencyConnection_delayDial__roaming_roamingcarrierconfig()1137 public void testCreateOutgoingEmergencyConnection_delayDial__roaming_roamingcarrierconfig() { 1138 // Setup test to not support SUPL on the non-DDS subscription 1139 doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any()); 1140 // Setup voice roaming scenario 1141 String testRoamingOperator = "001001"; 1142 String[] roamingPlmns = new String[1]; 1143 roamingPlmns[0] = testRoamingOperator; 1144 getTestContext().getCarrierConfig(0 /*subId*/).putStringArray( 1145 CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY, 1146 roamingPlmns); 1147 getTestContext().getCarrierConfig(0 /*subId*/).putInt( 1148 CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT, 1149 CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK); 1150 getTestContext().getCarrierConfig(0 /*subId*/).putString( 1151 CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0"); 1152 1153 Phone testPhone = setupConnectionServiceForDelayDial( 1154 false /* isRoaming */, true /* setOperatorName */, 1155 "TestTel" /* operator long name*/, "TestTel" /* operator short name */, 1156 testRoamingOperator /* operator numeric name */); 1157 verify(mPhoneSwitcher).overrideDefaultDataForEmergency(eq(0) /*phoneId*/ , 1158 eq(0) /*extensionTime*/, any()); 1159 } 1160 1161 /** 1162 * Verifies for an incoming call on the same SIM that we don't set 1163 * {@link android.telecom.Connection#EXTRA_ANSWERING_DROPS_FG_CALL} on the incoming call extras. 1164 * @throws Exception 1165 */ 1166 @Test 1167 @SmallTest testIncomingDoesntRequestDisconnect()1168 public void testIncomingDoesntRequestDisconnect() throws Exception { 1169 setupForCallTest(); 1170 1171 mBinderStub.createConnection(PHONE_ACCOUNT_HANDLE_1, "TC@1", 1172 new ConnectionRequest(PHONE_ACCOUNT_HANDLE_1, Uri.parse("tel:16505551212"), 1173 new Bundle()), 1174 true, false, null); 1175 waitForHandlerAction(mTestConnectionService.getHandler(), TIMEOUT_MS); 1176 assertEquals(1, mTestConnectionService.getAllConnections().size()); 1177 1178 // Make sure the extras do not indicate that it answering will disconnect another call. 1179 android.telecom.Connection connection = (android.telecom.Connection) 1180 mTestConnectionService.getAllConnections().toArray()[0]; 1181 assertFalse(connection.getExtras() != null && connection.getExtras().containsKey( 1182 android.telecom.Connection.EXTRA_ANSWERING_DROPS_FG_CALL)); 1183 } 1184 1185 /** 1186 * Verifies where there is another call on the same sub, we don't set 1187 * {@link android.telecom.Connection#EXTRA_ANSWERING_DROPS_FG_CALL} on the incoming call extras. 1188 * @throws Exception 1189 */ 1190 @Test 1191 @SmallTest testSecondCallSameSubWontDisconnect()1192 public void testSecondCallSameSubWontDisconnect() throws Exception { 1193 // Previous test gets us into a good enough state 1194 testIncomingDoesntRequestDisconnect(); 1195 1196 when(mCall.getState()).thenReturn(Call.State.ACTIVE); 1197 when(mCall2.getState()).thenReturn(Call.State.WAITING); 1198 when(mCall2.getLatestConnection()).thenReturn(mInternalConnection2); 1199 when(mPhone0.getRingingCall()).thenReturn(mCall2); 1200 1201 mBinderStub.createConnection(PHONE_ACCOUNT_HANDLE_1, "TC@2", 1202 new ConnectionRequest(PHONE_ACCOUNT_HANDLE_1, Uri.parse("tel:16505551213"), 1203 new Bundle()), 1204 true, false, null); 1205 waitForHandlerAction(mTestConnectionService.getHandler(), TIMEOUT_MS); 1206 assertEquals(2, mTestConnectionService.getAllConnections().size()); 1207 1208 // None of the connections should have the extra set. 1209 assertEquals(0, mTestConnectionService.getAllConnections().stream() 1210 .filter(c -> c.getExtras() != null && c.getExtras().containsKey( 1211 android.telecom.Connection.EXTRA_ANSWERING_DROPS_FG_CALL)) 1212 .count()); 1213 } 1214 1215 /** 1216 * Verifies where there is another call on the same sub, we don't set 1217 * {@link android.telecom.Connection#EXTRA_ANSWERING_DROPS_FG_CALL} on the incoming call extras. 1218 * @throws Exception 1219 */ 1220 @Test 1221 @SmallTest testSecondCallDifferentSubWillDisconnect()1222 public void testSecondCallDifferentSubWillDisconnect() throws Exception { 1223 // Previous test gets us into a good enough state 1224 testIncomingDoesntRequestDisconnect(); 1225 1226 when(mCall.getState()).thenReturn(Call.State.ACTIVE); 1227 when(mCall2.getState()).thenReturn(Call.State.WAITING); 1228 when(mCall2.getLatestConnection()).thenReturn(mInternalConnection2); 1229 // At this point the call is ringing on the second phone. 1230 when(mPhone0.getRingingCall()).thenReturn(null); 1231 when(mPhone1.getRingingCall()).thenReturn(mCall2); 1232 1233 mBinderStub.createConnection(PHONE_ACCOUNT_HANDLE_2, "TC@2", 1234 new ConnectionRequest(PHONE_ACCOUNT_HANDLE_2, Uri.parse("tel:16505551213"), 1235 new Bundle()), 1236 true, false, null); 1237 waitForHandlerAction(mTestConnectionService.getHandler(), TIMEOUT_MS); 1238 assertEquals(2, mTestConnectionService.getAllConnections().size()); 1239 1240 // The incoming connection should have the extra set. 1241 assertEquals(1, mTestConnectionService.getAllConnections().stream() 1242 .filter(c -> c.getExtras() != null && c.getExtras().containsKey( 1243 android.telecom.Connection.EXTRA_ANSWERING_DROPS_FG_CALL)) 1244 .count()); 1245 } 1246 1247 private static final PhoneAccountHandle SUB1_HANDLE = new PhoneAccountHandle( 1248 new ComponentName("test", "class"), "1"); 1249 private static final PhoneAccountHandle SUB2_HANDLE = new PhoneAccountHandle( 1250 new ComponentName("test", "class"), "2"); 1251 1252 @Test 1253 @SmallTest testDontDisconnectSameSub()1254 public void testDontDisconnectSameSub() { 1255 ArrayList<android.telecom.Connection> tcs = new ArrayList<>(); 1256 SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false); 1257 tcs.add(tc1); 1258 TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(tcs, SUB1_HANDLE); 1259 // Would've preferred to use mockito, but can't mock out TelephonyConnection/Connection 1260 // easily. 1261 assertFalse(tc1.wasDisconnected); 1262 } 1263 1264 @Test 1265 @SmallTest testDontDisconnectEmergency()1266 public void testDontDisconnectEmergency() { 1267 ArrayList<android.telecom.Connection> tcs = new ArrayList<>(); 1268 SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, true); 1269 tcs.add(tc1); 1270 TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(tcs, SUB2_HANDLE); 1271 // Other call is an emergency call, so don't disconnect it. 1272 assertFalse(tc1.wasDisconnected); 1273 } 1274 1275 @Test 1276 @SmallTest testDontDisconnectExternal()1277 public void testDontDisconnectExternal() { 1278 ArrayList<android.telecom.Connection> tcs = new ArrayList<>(); 1279 SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 1280 android.telecom.Connection.PROPERTY_IS_EXTERNAL_CALL, false); 1281 tcs.add(tc1); 1282 TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(tcs, SUB2_HANDLE); 1283 // Other call is an external call, so don't disconnect it. 1284 assertFalse(tc1.wasDisconnected); 1285 } 1286 1287 @Test 1288 @SmallTest testDisconnectDifferentSub()1289 public void testDisconnectDifferentSub() { 1290 ArrayList<android.telecom.Connection> tcs = new ArrayList<>(); 1291 SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false); 1292 tcs.add(tc1); 1293 TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(tcs, SUB2_HANDLE); 1294 assertTrue(tc1.wasDisconnected); 1295 } 1296 1297 @Test 1298 @SmallTest testDisconnectDifferentSubTwoCalls()1299 public void testDisconnectDifferentSubTwoCalls() { 1300 ArrayList<android.telecom.Connection> tcs = new ArrayList<>(); 1301 SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false); 1302 SimpleTelephonyConnection tc2 = createTestConnection(SUB1_HANDLE, 0, false); 1303 1304 tcs.add(tc1); 1305 tcs.add(tc2); 1306 TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(tcs, SUB2_HANDLE); 1307 assertTrue(tc1.wasDisconnected); 1308 assertTrue(tc2.wasDisconnected); 1309 } 1310 createTestConnection(PhoneAccountHandle handle, int properties, boolean isEmergency)1311 private SimpleTelephonyConnection createTestConnection(PhoneAccountHandle handle, 1312 int properties, boolean isEmergency) { 1313 SimpleTelephonyConnection connection = new SimpleTelephonyConnection(); 1314 connection.setShouldTreatAsEmergencyCall(isEmergency); 1315 connection.setConnectionProperties(properties); 1316 connection.setPhoneAccountHandle(handle); 1317 return connection; 1318 } 1319 1320 /** 1321 * Setup the mess of mocks for {@link #testSecondCallSameSubWontDisconnect()} and 1322 * {@link #testIncomingDoesntRequestDisconnect()}. 1323 */ setupForCallTest()1324 private void setupForCallTest() { 1325 // Setup a bunch of stuff. Blech. 1326 mTestConnectionService.setReadyForTest(); 1327 mPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_IN_SERVICE, 1328 false /*isEmergencyOnly*/); 1329 when(mCall.getState()).thenReturn(Call.State.INCOMING); 1330 when(mCall.getPhone()).thenReturn(mPhone0); 1331 when(mPhone0.getRingingCall()).thenReturn(mCall); 1332 mPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_IN_SERVICE, 1333 false /*isEmergencyOnly*/); 1334 when(mCall2.getPhone()).thenReturn(mPhone1); 1335 List<Phone> phones = new ArrayList<>(2); 1336 doReturn(true).when(mPhone0).isRadioOn(); 1337 doReturn(true).when(mPhone1).isRadioOn(); 1338 doReturn(GSM_PHONE).when(mPhone0).getPhoneType(); 1339 doReturn(GSM_PHONE).when(mPhone1).getPhoneType(); 1340 phones.add(mPhone0); 1341 phones.add(mPhone1); 1342 setPhones(phones); 1343 when(mPhoneUtilsProxy.getSubIdForPhoneAccountHandle(eq(PHONE_ACCOUNT_HANDLE_1))) 1344 .thenReturn(0); 1345 when(mSubscriptionManagerProxy.getPhoneId(0)).thenReturn(0); 1346 when(mPhoneFactoryProxy.getPhone(eq(0))).thenReturn(mPhone0); 1347 when(mPhoneUtilsProxy.getSubIdForPhoneAccountHandle(eq(PHONE_ACCOUNT_HANDLE_2))) 1348 .thenReturn(1); 1349 when(mSubscriptionManagerProxy.getPhoneId(1)).thenReturn(1); 1350 when(mPhoneFactoryProxy.getPhone(eq(1))).thenReturn(mPhone1); 1351 setupDeviceConfig(mPhone0, mPhone1, 1); 1352 1353 when(mInternalConnection.getCall()).thenReturn(mCall); 1354 when(mInternalConnection.getState()).thenReturn(Call.State.ACTIVE); 1355 when(mInternalConnection2.getCall()).thenReturn(mCall2); 1356 when(mInternalConnection2.getState()).thenReturn(Call.State.WAITING); 1357 } 1358 1359 /** 1360 * Set up a mock MSIM device with TEST_ADDRESS set as an emergency number. 1361 * @param isRoaming whether it is roaming 1362 * @param setOperatorName whether operator name needs to set 1363 * @param operatorNameLongName the operator long name if needs to set 1364 * @param operatorNameShortName the operator short name if needs to set 1365 * @param operatorNameNumeric the operator numeric name if needs to set 1366 * @return the Phone associated with slot 0. 1367 */ setupConnectionServiceForDelayDial(boolean isRoaming, boolean setOperatorName, String operatorNameLongName, String operatorNameShortName, String operatorNameNumeric)1368 private Phone setupConnectionServiceForDelayDial(boolean isRoaming, boolean setOperatorName, 1369 String operatorNameLongName, String operatorNameShortName, 1370 String operatorNameNumeric) { 1371 ConnectionRequest connectionRequest = new ConnectionRequest.Builder() 1372 .setAccountHandle(PHONE_ACCOUNT_HANDLE_1) 1373 .setAddress(TEST_ADDRESS) 1374 .build(); 1375 Phone testPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_IN_SERVICE, 1376 false /*isEmergencyOnly*/); 1377 Phone testPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_OUT_OF_SERVICE, 1378 false /*isEmergencyOnly*/); 1379 List<Phone> phones = new ArrayList<>(2); 1380 doReturn(true).when(testPhone0).isRadioOn(); 1381 doReturn(true).when(testPhone1).isRadioOn(); 1382 phones.add(testPhone0); 1383 phones.add(testPhone1); 1384 setPhones(phones); 1385 setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_1, testPhone0); 1386 setupDeviceConfig(testPhone0, testPhone1, 1); 1387 doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber( 1388 TEST_ADDRESS.getSchemeSpecificPart()); 1389 HashMap<Integer, List<EmergencyNumber>> emergencyNumbers = new HashMap<>(1); 1390 List<EmergencyNumber> numbers = new ArrayList<>(); 1391 numbers.add(setupEmergencyNumber(TEST_ADDRESS)); 1392 emergencyNumbers.put(0 /*subId*/, numbers); 1393 doReturn(emergencyNumbers).when(mTelephonyManagerProxy).getCurrentEmergencyNumberList(); 1394 doReturn(2).when(mTelephonyManagerProxy).getPhoneCount(); 1395 testPhone0.getServiceState().setRoaming(isRoaming); 1396 if (setOperatorName) { 1397 testPhone0.getServiceState().setOperatorName(operatorNameLongName, 1398 operatorNameShortName, operatorNameNumeric); 1399 } 1400 mConnection = mTestConnectionService.onCreateOutgoingConnection( 1401 PHONE_ACCOUNT_HANDLE_1, connectionRequest); 1402 assertNotNull("test connection was not set up correctly.", mConnection); 1403 return testPhone0; 1404 } 1405 1406 /** 1407 * Set up a mock MSIM device with TEST_ADDRESS set as an emergency number in airplane mode. 1408 * @return the Phone associated with slot 0. 1409 */ setupConnectionServiceInApm()1410 private Phone setupConnectionServiceInApm() { 1411 ConnectionRequest connectionRequest = new ConnectionRequest.Builder() 1412 .setAccountHandle(PHONE_ACCOUNT_HANDLE_1) 1413 .setAddress(TEST_ADDRESS) 1414 .build(); 1415 Phone testPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_POWER_OFF, 1416 false /*isEmergencyOnly*/); 1417 Phone testPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_POWER_OFF, 1418 false /*isEmergencyOnly*/); 1419 doReturn(GSM_PHONE).when(testPhone0).getPhoneType(); 1420 doReturn(GSM_PHONE).when(testPhone1).getPhoneType(); 1421 List<Phone> phones = new ArrayList<>(2); 1422 doReturn(false).when(testPhone0).isRadioOn(); 1423 doReturn(false).when(testPhone1).isRadioOn(); 1424 phones.add(testPhone0); 1425 phones.add(testPhone1); 1426 setPhones(phones); 1427 setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_1, testPhone0); 1428 setupDeviceConfig(testPhone0, testPhone1, 0); 1429 doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber( 1430 TEST_ADDRESS.getSchemeSpecificPart()); 1431 HashMap<Integer, List<EmergencyNumber>> emergencyNumbers = new HashMap<>(1); 1432 List<EmergencyNumber> numbers = new ArrayList<>(); 1433 numbers.add(setupEmergencyNumber(TEST_ADDRESS)); 1434 emergencyNumbers.put(0 /*subId*/, numbers); 1435 doReturn(emergencyNumbers).when(mTelephonyManagerProxy).getCurrentEmergencyNumberList(); 1436 doReturn(2).when(mTelephonyManagerProxy).getPhoneCount(); 1437 1438 mConnection = mTestConnectionService.onCreateOutgoingConnection( 1439 PHONE_ACCOUNT_HANDLE_1, connectionRequest); 1440 assertNotNull("test connection was not set up correctly.", mConnection); 1441 1442 return testPhone0; 1443 } 1444 setupEmergencyNumber(Uri address)1445 private EmergencyNumber setupEmergencyNumber(Uri address) { 1446 return new EmergencyNumber(address.getSchemeSpecificPart(), "", "", 1447 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED, 1448 Collections.emptyList(), 1449 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_SIM, 1450 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY); 1451 } 1452 setupHandleToPhoneMap(PhoneAccountHandle handle, Phone phone)1453 private void setupHandleToPhoneMap(PhoneAccountHandle handle, Phone phone) { 1454 // use subId 0 1455 when(mPhoneUtilsProxy.getSubIdForPhoneAccountHandle(eq(handle))).thenReturn(0); 1456 when(mSubscriptionManagerProxy.getPhoneId(eq(0))).thenReturn(0); 1457 when(mPhoneFactoryProxy.getPhone(eq(0))).thenReturn(phone); 1458 } 1459 getSuppServiceNotification(int notificationType, int code)1460 private AsyncResult getSuppServiceNotification(int notificationType, int code) { 1461 SuppServiceNotification notification = new SuppServiceNotification(); 1462 notification.notificationType = notificationType; 1463 notification.code = code; 1464 return new AsyncResult(null, notification, null); 1465 } 1466 makeTestPhone(int phoneId, int serviceState, boolean isEmergencyOnly)1467 private Phone makeTestPhone(int phoneId, int serviceState, boolean isEmergencyOnly) { 1468 Phone phone = mock(Phone.class); 1469 ServiceState testServiceState = new ServiceState(); 1470 testServiceState.setState(serviceState); 1471 testServiceState.setEmergencyOnly(isEmergencyOnly); 1472 when(phone.getContext()).thenReturn(mContext); 1473 when(phone.getServiceState()).thenReturn(testServiceState); 1474 when(phone.getPhoneId()).thenReturn(phoneId); 1475 when(phone.getDefaultPhone()).thenReturn(phone); 1476 when(phone.getEmergencyNumberTracker()).thenReturn(mEmergencyNumberTracker); 1477 when(phone.getServiceStateTracker()).thenReturn(mSST); 1478 doNothing().when(phone).registerForPreciseCallStateChanged(any(Handler.class), anyInt(), 1479 any(Object.class)); 1480 when(mEmergencyNumberTracker.getEmergencyNumber(anyString())).thenReturn(null); 1481 return phone; 1482 } 1483 1484 // Setup 2 SIM device setupDeviceConfig(Phone slot0Phone, Phone slot1Phone, int defaultVoicePhoneId)1485 private void setupDeviceConfig(Phone slot0Phone, Phone slot1Phone, int defaultVoicePhoneId) { 1486 when(mTelephonyManagerProxy.getPhoneCount()).thenReturn(2); 1487 when(mSubscriptionManagerProxy.getDefaultVoicePhoneId()).thenReturn(defaultVoicePhoneId); 1488 when(mPhoneFactoryProxy.getPhone(eq(SLOT_0_PHONE_ID))).thenReturn(slot0Phone); 1489 when(mPhoneFactoryProxy.getPhone(eq(SLOT_1_PHONE_ID))).thenReturn(slot1Phone); 1490 } 1491 setPhoneRadioAccessFamily(Phone phone, int radioAccessFamily)1492 private void setPhoneRadioAccessFamily(Phone phone, int radioAccessFamily) { 1493 when(phone.getRadioAccessFamily()).thenReturn(radioAccessFamily); 1494 } 1495 setPhoneSlotState(int slotId, int slotState)1496 private void setPhoneSlotState(int slotId, int slotState) { 1497 when(mSubscriptionManagerProxy.getSimStateForSlotIdx(slotId)).thenReturn(slotState); 1498 } 1499 setSlotHasIccCard(int slotId, boolean isInserted)1500 private void setSlotHasIccCard(int slotId, boolean isInserted) { 1501 when(mTelephonyManagerProxy.hasIccCard(slotId)).thenReturn(isInserted); 1502 } 1503 setDefaultPhone(Phone phone)1504 private void setDefaultPhone(Phone phone) { 1505 when(mPhoneFactoryProxy.getDefaultPhone()).thenReturn(phone); 1506 } 1507 setPhones(List<Phone> phones)1508 private void setPhones(List<Phone> phones) { 1509 when(mPhoneFactoryProxy.getPhones()).thenReturn(phones.toArray(new Phone[phones.size()])); 1510 when(mPhoneFactoryProxy.getDefaultPhone()).thenReturn(phones.get(0)); 1511 } 1512 setPhonesDialConnection(Phone phone, Connection c)1513 private void setPhonesDialConnection(Phone phone, Connection c) { 1514 try { 1515 when(phone.dial(anyString(), any(), any())).thenReturn(c); 1516 } catch (CallStateException e) { 1517 // this shouldn't happen 1518 fail(); 1519 } 1520 } 1521 } 1522