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