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 17package com.android.services.telephony; 18 19import static junit.framework.Assert.assertEquals; 20import static junit.framework.Assert.assertTrue; 21import static junit.framework.Assert.fail; 22 23import static org.mockito.ArgumentMatchers.any; 24import static org.mockito.ArgumentMatchers.anyInt; 25import static org.mockito.ArgumentMatchers.anyString; 26import static org.mockito.Matchers.eq; 27import static org.mockito.Mockito.mock; 28import static org.mockito.Mockito.never; 29import static org.mockito.Mockito.verify; 30import static org.mockito.Mockito.when; 31 32import android.net.Uri; 33import android.os.AsyncResult; 34import android.os.Bundle; 35import android.os.Handler; 36import android.support.test.filters.FlakyTest; 37import android.support.test.runner.AndroidJUnit4; 38import android.telecom.DisconnectCause; 39import android.telecom.TelecomManager; 40import android.telephony.RadioAccessFamily; 41import android.telephony.ServiceState; 42import android.telephony.TelephonyManager; 43import android.test.suitebuilder.annotation.SmallTest; 44 45import com.android.TelephonyTestBase; 46import com.android.internal.telephony.CallStateException; 47import com.android.internal.telephony.Connection; 48import com.android.internal.telephony.Phone; 49import com.android.internal.telephony.gsm.SuppServiceNotification; 50 51import org.junit.After; 52import org.junit.Before; 53import org.junit.Test; 54import org.junit.runner.RunWith; 55import org.mockito.ArgumentCaptor; 56import org.mockito.Mock; 57 58import java.util.ArrayList; 59import java.util.List; 60 61/** 62 * Unit tests for TelephonyConnectionService. 63 */ 64 65@RunWith(AndroidJUnit4.class) 66public class TelephonyConnectionServiceTest extends TelephonyTestBase { 67 68 private static final long TIMEOUT_MS = 100; 69 private static final int SLOT_0_PHONE_ID = 0; 70 private static final int SLOT_1_PHONE_ID = 1; 71 72 @Mock TelephonyConnectionService.TelephonyManagerProxy mTelephonyManagerProxy; 73 @Mock TelephonyConnectionService.SubscriptionManagerProxy mSubscriptionManagerProxy; 74 @Mock TelephonyConnectionService.PhoneFactoryProxy mPhoneFactoryProxy; 75 76 TelephonyConnectionService mTestConnectionService; 77 78 @Before 79 public void setUp() throws Exception { 80 super.setUp(); 81 mTestConnectionService = new TelephonyConnectionService(); 82 mTestConnectionService.setPhoneFactoryProxy(mPhoneFactoryProxy); 83 mTestConnectionService.setTelephonyManagerProxy(mTelephonyManagerProxy); 84 mTestConnectionService.setSubscriptionManagerProxy(mSubscriptionManagerProxy); 85 } 86 87 @After 88 public void tearDown() throws Exception { 89 mTestConnectionService = null; 90 super.tearDown(); 91 } 92 93 /** 94 * Prerequisites: 95 * - MSIM Device, two slots with SIMs inserted 96 * - Users default Voice SIM choice is IN_SERVICE 97 * 98 * Result: getFirstPhoneForEmergencyCall returns the default Voice SIM choice. 99 */ 100 @Test 101 @SmallTest 102 public void testDefaultVoiceSimInService() { 103 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_IN_SERVICE, 104 false /*isEmergencyOnly*/); 105 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 106 true /*isEmergencyOnly*/); 107 setDefaultPhone(slot0Phone); 108 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 109 110 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 111 112 assertEquals(slot0Phone, resultPhone); 113 } 114 115 /** 116 * Prerequisites: 117 * - MSIM Device, two slots with SIMs inserted 118 * - Slot 0 is OUT_OF_SERVICE, Slot 1 is OUT_OF_SERVICE (emergency calls only) 119 * 120 * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone 121 */ 122 @Test 123 @SmallTest 124 public void testSlot1EmergencyOnly() { 125 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 126 false /*isEmergencyOnly*/); 127 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 128 true /*isEmergencyOnly*/); 129 setDefaultPhone(slot0Phone); 130 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 131 132 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 133 134 assertEquals(slot1Phone, resultPhone); 135 } 136 137 /** 138 * Prerequisites: 139 * - MSIM Device, two slots with SIMs inserted 140 * - Slot 0 is OUT_OF_SERVICE, Slot 1 is IN_SERVICE 141 * 142 * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone 143 */ 144 @Test 145 @SmallTest 146 public void testSlot1InService() { 147 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 148 false /*isEmergencyOnly*/); 149 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_IN_SERVICE, 150 false /*isEmergencyOnly*/); 151 setDefaultPhone(slot0Phone); 152 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 153 154 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 155 156 assertEquals(slot1Phone, resultPhone); 157 } 158 159 /** 160 * Prerequisites: 161 * - MSIM Device, two slots with SIMs inserted 162 * - Slot 0 is PUK locked, Slot 1 is ready 163 * - Slot 0 is LTE capable, Slot 1 is GSM capable 164 * 165 * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone. Although Slot 0 is more 166 * capable, it is locked, so use the other slot. 167 */ 168 @Test 169 @SmallTest 170 public void testSlot0PukLocked() { 171 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 172 false /*isEmergencyOnly*/); 173 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 174 false /*isEmergencyOnly*/); 175 setDefaultPhone(slot0Phone); 176 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 177 // Set Slot 0 to be PUK locked 178 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_PUK_REQUIRED); 179 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY); 180 // Make Slot 0 higher capability 181 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE); 182 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_GSM); 183 184 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 185 186 assertEquals(slot1Phone, resultPhone); 187 } 188 189 /** 190 * Prerequisites: 191 * - MSIM Device, two slots with SIMs inserted 192 * - Slot 0 is PIN locked, Slot 1 is ready 193 * - Slot 0 is LTE capable, Slot 1 is GSM capable 194 * 195 * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone. Although Slot 0 is more 196 * capable, it is locked, so use the other slot. 197 */ 198 @Test 199 @SmallTest 200 public void testSlot0PinLocked() { 201 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 202 false /*isEmergencyOnly*/); 203 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 204 false /*isEmergencyOnly*/); 205 setDefaultPhone(slot0Phone); 206 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 207 // Set Slot 0 to be PUK locked 208 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_PIN_REQUIRED); 209 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY); 210 // Make Slot 0 higher capability 211 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE); 212 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_GSM); 213 214 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 215 216 assertEquals(slot1Phone, resultPhone); 217 } 218 219 /** 220 * Prerequisites: 221 * - MSIM Device, two slots with SIMs inserted 222 * - Slot 1 is PUK locked, Slot 0 is ready 223 * - Slot 1 is LTE capable, Slot 0 is GSM capable 224 * 225 * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone. Although Slot 1 is more 226 * capable, it is locked, so use the other slot. 227 */ 228 @Test 229 @SmallTest 230 public void testSlot1PukLocked() { 231 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 232 false /*isEmergencyOnly*/); 233 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 234 false /*isEmergencyOnly*/); 235 setDefaultPhone(slot0Phone); 236 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 237 // Set Slot 1 to be PUK locked 238 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY); 239 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_PUK_REQUIRED); 240 // Make Slot 1 higher capability 241 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM); 242 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE); 243 244 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 245 246 assertEquals(slot0Phone, resultPhone); 247 } 248 249 /** 250 * Prerequisites: 251 * - MSIM Device, two slots with SIMs inserted 252 * - Slot 1 is PIN locked, Slot 0 is ready 253 * - Slot 1 is LTE capable, Slot 0 is GSM capable 254 * 255 * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone. Although Slot 1 is more 256 * capable, it is locked, so use the other slot. 257 */ 258 @Test 259 @SmallTest 260 public void testSlot1PinLocked() { 261 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 262 false /*isEmergencyOnly*/); 263 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 264 false /*isEmergencyOnly*/); 265 setDefaultPhone(slot0Phone); 266 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 267 // Set Slot 1 to be PUK locked 268 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY); 269 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_PIN_REQUIRED); 270 // Make Slot 1 higher capability 271 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM); 272 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE); 273 274 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 275 276 assertEquals(slot0Phone, resultPhone); 277 } 278 279 /** 280 * Prerequisites: 281 * - MSIM Device, two slots with SIMs inserted 282 * - Slot 1 is LTE capable, Slot 0 is GSM capable 283 * 284 * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it is more capable 285 */ 286 @Test 287 @SmallTest 288 public void testSlot1HigherCapablity() { 289 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 290 false /*isEmergencyOnly*/); 291 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 292 false /*isEmergencyOnly*/); 293 setDefaultPhone(slot0Phone); 294 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 295 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY); 296 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY); 297 // Make Slot 1 higher capability 298 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM); 299 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE); 300 301 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 302 303 assertEquals(slot1Phone, resultPhone); 304 } 305 306 /** 307 * Prerequisites: 308 * - MSIM Device, two slots with SIMs inserted 309 * - Slot 1 is GSM/LTE capable, Slot 0 is GSM capable 310 * 311 * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it has more 312 * capabilities. 313 */ 314 @Test 315 @SmallTest 316 public void testSlot1MoreCapabilities() { 317 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 318 false /*isEmergencyOnly*/); 319 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 320 false /*isEmergencyOnly*/); 321 setDefaultPhone(slot0Phone); 322 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 323 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY); 324 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY); 325 // Make Slot 1 more capable 326 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE); 327 setPhoneRadioAccessFamily(slot1Phone, 328 RadioAccessFamily.RAF_GSM | RadioAccessFamily.RAF_LTE); 329 330 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 331 332 assertEquals(slot1Phone, resultPhone); 333 } 334 335 /** 336 * Prerequisites: 337 * - MSIM Device, two slots with SIMs inserted 338 * - Both SIMs PUK Locked 339 * - Slot 0 is LTE capable, Slot 1 is GSM capable 340 * 341 * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone because it is more capable, 342 * ignoring that both SIMs are PUK locked. 343 */ 344 @Test 345 @SmallTest 346 public void testSlot0MoreCapableBothPukLocked() { 347 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 348 false /*isEmergencyOnly*/); 349 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 350 false /*isEmergencyOnly*/); 351 setDefaultPhone(slot0Phone); 352 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 353 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_PUK_REQUIRED); 354 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_PUK_REQUIRED); 355 // Make Slot 0 higher capability 356 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE); 357 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_GSM); 358 359 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 360 361 assertEquals(slot0Phone, resultPhone); 362 } 363 364 /** 365 * Prerequisites: 366 * - MSIM Device, two slots with SIMs inserted 367 * - Both SIMs have the same capability 368 * 369 * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone because it is the first slot. 370 */ 371 @Test 372 @SmallTest 373 public void testEqualCapabilityTwoSimsInserted() { 374 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 375 false /*isEmergencyOnly*/); 376 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 377 false /*isEmergencyOnly*/); 378 setDefaultPhone(slot0Phone); 379 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 380 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY); 381 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY); 382 // Make Capability the same 383 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE); 384 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE); 385 // Two SIMs inserted 386 setSlotHasIccCard(SLOT_0_PHONE_ID, true /*isInserted*/); 387 setSlotHasIccCard(SLOT_1_PHONE_ID, true /*isInserted*/); 388 389 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 390 391 assertEquals(slot0Phone, resultPhone); 392 } 393 394 /** 395 * Prerequisites: 396 * - MSIM Device, only slot 0 inserted 397 * - Both SIMs have the same capability 398 * 399 * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone because it is the only one 400 * with a SIM inserted 401 */ 402 @Test 403 @SmallTest 404 public void testEqualCapabilitySim0Inserted() { 405 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 406 false /*isEmergencyOnly*/); 407 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 408 false /*isEmergencyOnly*/); 409 setDefaultPhone(slot0Phone); 410 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 411 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY); 412 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT); 413 // Make Capability the same 414 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE); 415 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE); 416 // Slot 0 has SIM inserted. 417 setSlotHasIccCard(SLOT_0_PHONE_ID, true /*isInserted*/); 418 setSlotHasIccCard(SLOT_1_PHONE_ID, false /*isInserted*/); 419 420 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 421 422 assertEquals(slot0Phone, resultPhone); 423 } 424 425 /** 426 * Prerequisites: 427 * - MSIM Device, only slot 1 inserted 428 * - Both SIMs have the same capability 429 * 430 * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it is the only one 431 * with a SIM inserted 432 */ 433 @Test 434 @SmallTest 435 public void testEqualCapabilitySim1Inserted() { 436 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 437 false /*isEmergencyOnly*/); 438 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 439 false /*isEmergencyOnly*/); 440 setDefaultPhone(slot0Phone); 441 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 442 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT); 443 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY); 444 // Make Capability the same 445 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE); 446 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE); 447 // Slot 1 has SIM inserted. 448 setSlotHasIccCard(SLOT_0_PHONE_ID, false /*isInserted*/); 449 setSlotHasIccCard(SLOT_1_PHONE_ID, true /*isInserted*/); 450 451 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 452 453 assertEquals(slot1Phone, resultPhone); 454 } 455 456 /** 457 * Prerequisites: 458 * - MSIM Device, no SIMs inserted 459 * - SIM 1 has the higher capability 460 * 461 * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone, since it is a higher 462 * capability 463 */ 464 @Test 465 @SmallTest 466 public void testSim1HigherCapabilityNoSimsInserted() { 467 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 468 false /*isEmergencyOnly*/); 469 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 470 false /*isEmergencyOnly*/); 471 setDefaultPhone(slot0Phone); 472 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 473 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT); 474 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT); 475 // Make Capability the same 476 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM); 477 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE); 478 // No SIMs inserted 479 setSlotHasIccCard(SLOT_0_PHONE_ID, false /*isInserted*/); 480 setSlotHasIccCard(SLOT_1_PHONE_ID, false /*isInserted*/); 481 482 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 483 484 assertEquals(slot1Phone, resultPhone); 485 } 486 487 /** 488 * Prerequisites: 489 * - MSIM Device, no SIMs inserted 490 * - Both SIMs have the same capability (Unknown) 491 * 492 * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone, since it is the first slot. 493 */ 494 @Test 495 @SmallTest 496 public void testEqualCapabilityNoSimsInserted() { 497 Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 498 false /*isEmergencyOnly*/); 499 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 500 false /*isEmergencyOnly*/); 501 setDefaultPhone(slot0Phone); 502 setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID); 503 setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT); 504 setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT); 505 // Make Capability the same 506 setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_UNKNOWN); 507 setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_UNKNOWN); 508 // No SIMs inserted 509 setSlotHasIccCard(SLOT_0_PHONE_ID, false /*isInserted*/); 510 setSlotHasIccCard(SLOT_1_PHONE_ID, false /*isInserted*/); 511 512 Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall(); 513 514 assertEquals(slot0Phone, resultPhone); 515 } 516 517 /** 518 * The modem has returned a temporary error when placing an emergency call on a phone with one 519 * SIM slot. 520 * 521 * Verify that dial is called on the same phone again when retryOutgoingOriginalConnection is 522 * called. 523 */ 524 @Test 525 @FlakyTest 526 @SmallTest 527 public void testRetryOutgoingOriginalConnection_redialTempFailOneSlot() { 528 TestTelephonyConnection c = new TestTelephonyConnection(); 529 Phone slot0Phone = c.getPhone(); 530 when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID); 531 List<Phone> phones = new ArrayList<>(1); 532 phones.add(slot0Phone); 533 setPhones(phones); 534 c.setAddress(Uri.parse("tel:+16505551212"), TelecomManager.PRESENTATION_ALLOWED); 535 536 mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/); 537 538 // We never need to be notified in telecom that the PhoneAccount has changed, because it 539 // was redialed on the same slot 540 assertEquals(0, c.getNotifyPhoneAccountChangedCount()); 541 try { 542 verify(slot0Phone).dial(anyString(), any()); 543 } catch (CallStateException e) { 544 // This shouldn't happen 545 fail(); 546 } 547 } 548 549 /** 550 * The modem has returned a permanent failure when placing an emergency call on a phone with one 551 * SIM slot. 552 * 553 * Verify that the connection is set to disconnected with an error disconnect cause and dial is 554 * not called. 555 */ 556 @Test 557 @FlakyTest 558 @SmallTest 559 public void testRetryOutgoingOriginalConnection_redialPermFailOneSlot() { 560 TestTelephonyConnection c = new TestTelephonyConnection(); 561 Phone slot0Phone = c.getPhone(); 562 when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID); 563 List<Phone> phones = new ArrayList<>(1); 564 phones.add(slot0Phone); 565 setPhones(phones); 566 c.setAddress(Uri.parse("tel:+16505551212"), TelecomManager.PRESENTATION_ALLOWED); 567 568 mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/); 569 570 // We never need to be notified in telecom that the PhoneAccount has changed, because it 571 // was never redialed 572 assertEquals(0, c.getNotifyPhoneAccountChangedCount()); 573 try { 574 verify(slot0Phone, never()).dial(anyString(), any()); 575 } catch (CallStateException e) { 576 // This shouldn't happen 577 fail(); 578 } 579 assertEquals(c.getState(), android.telecom.Connection.STATE_DISCONNECTED); 580 assertEquals(c.getDisconnectCause().getCode(), DisconnectCause.ERROR); 581 } 582 583 /** 584 * The modem has returned a temporary failure when placing an emergency call on a phone with two 585 * SIM slots. 586 * 587 * Verify that the emergency call is dialed on the other slot and telecom is notified of the new 588 * PhoneAccount. 589 */ 590 @Test 591 @FlakyTest 592 @SmallTest 593 public void testRetryOutgoingOriginalConnection_redialTempFailTwoSlot() { 594 TestTelephonyConnection c = new TestTelephonyConnection(); 595 Phone slot0Phone = c.getPhone(); 596 when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID); 597 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 598 false /*isEmergencyOnly*/); 599 setPhonesDialConnection(slot1Phone, c.getOriginalConnection()); 600 c.setAddress(Uri.parse("tel:+16505551212"), TelecomManager.PRESENTATION_ALLOWED); 601 List<Phone> phones = new ArrayList<>(2); 602 phones.add(slot0Phone); 603 phones.add(slot1Phone); 604 setPhones(phones); 605 606 mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/); 607 608 // The cache should still contain all of the Phones, since it was a temporary failure. 609 assertEquals(2, mTestConnectionService.mEmergencyRetryCache.second.size()); 610 // We need to be notified in Telecom that the PhoneAccount has changed, because it was 611 // redialed on another slot 612 assertEquals(1, c.getNotifyPhoneAccountChangedCount()); 613 try { 614 verify(slot1Phone).dial(anyString(), any()); 615 } catch (CallStateException e) { 616 // This shouldn't happen 617 fail(); 618 } 619 } 620 621 /** 622 * The modem has returned a temporary failure when placing an emergency call on a phone with two 623 * SIM slots. 624 * 625 * Verify that the emergency call is dialed on the other slot and telecom is notified of the new 626 * PhoneAccount. 627 */ 628 @Test 629 @FlakyTest 630 @SmallTest 631 public void testRetryOutgoingOriginalConnection_redialPermFailTwoSlot() { 632 TestTelephonyConnection c = new TestTelephonyConnection(); 633 Phone slot0Phone = c.getPhone(); 634 when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID); 635 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 636 false /*isEmergencyOnly*/); 637 setPhonesDialConnection(slot1Phone, c.getOriginalConnection()); 638 c.setAddress(Uri.parse("tel:+16505551212"), TelecomManager.PRESENTATION_ALLOWED); 639 List<Phone> phones = new ArrayList<>(2); 640 phones.add(slot0Phone); 641 phones.add(slot1Phone); 642 setPhones(phones); 643 644 mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/); 645 646 // The cache should only contain the slot1Phone. 647 assertEquals(1, mTestConnectionService.mEmergencyRetryCache.second.size()); 648 // We need to be notified in Telecom that the PhoneAccount has changed, because it was 649 // redialed on another slot 650 assertEquals(1, c.getNotifyPhoneAccountChangedCount()); 651 try { 652 verify(slot1Phone).dial(anyString(), any()); 653 } catch (CallStateException e) { 654 // This shouldn't happen 655 fail(); 656 } 657 } 658 659 /** 660 * The modem has returned a temporary failure twice while placing an emergency call on a phone 661 * with two SIM slots. 662 * 663 * Verify that the emergency call is dialed on slot 1 and then on slot 0 and telecom is 664 * notified of this twice. 665 */ 666 @Test 667 @FlakyTest 668 @SmallTest 669 public void testRetryOutgoingOriginalConnection_redialTempFailTwoSlot_twoFailure() { 670 TestTelephonyConnection c = new TestTelephonyConnection(); 671 Phone slot0Phone = c.getPhone(); 672 when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID); 673 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 674 false /*isEmergencyOnly*/); 675 setPhonesDialConnection(slot1Phone, c.getOriginalConnection()); 676 c.setAddress(Uri.parse("tel:+16505551212"), TelecomManager.PRESENTATION_ALLOWED); 677 List<Phone> phones = new ArrayList<>(2); 678 phones.add(slot0Phone); 679 phones.add(slot1Phone); 680 setPhones(phones); 681 682 // First Temporary failure 683 mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/); 684 // Set the Phone to the new phone that was just used to dial. 685 c.setMockPhone(slot1Phone); 686 // The cache should still contain all of the Phones, since it was a temporary failure. 687 assertEquals(2, mTestConnectionService.mEmergencyRetryCache.second.size()); 688 // Make sure slot 1 is next in the queue. 689 assertEquals(slot1Phone, mTestConnectionService.mEmergencyRetryCache.second.peek()); 690 // Second Temporary failure 691 mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/); 692 // Set the Phone to the new phone that was just used to dial. 693 c.setMockPhone(slot0Phone); 694 // The cache should still contain all of the Phones, since it was a temporary failure. 695 assertEquals(2, mTestConnectionService.mEmergencyRetryCache.second.size()); 696 // Make sure slot 0 is next in the queue. 697 assertEquals(slot0Phone, mTestConnectionService.mEmergencyRetryCache.second.peek()); 698 699 // We need to be notified in Telecom that the PhoneAccount has changed, because it was 700 // redialed on another slot 701 assertEquals(2, c.getNotifyPhoneAccountChangedCount()); 702 try { 703 verify(slot0Phone).dial(anyString(), any()); 704 verify(slot1Phone).dial(anyString(), any()); 705 } catch (CallStateException e) { 706 // This shouldn't happen 707 fail(); 708 } 709 } 710 711 /** 712 * The modem has returned a permanent failure twice while placing an emergency call on a phone 713 * with two SIM slots. 714 * 715 * Verify that the emergency call is dialed on slot 1 and then disconnected and telecom is 716 * notified of the change to slot 1. 717 */ 718 @Test 719 @FlakyTest 720 @SmallTest 721 public void testRetryOutgoingOriginalConnection_redialPermFailTwoSlot_twoFailure() { 722 TestTelephonyConnection c = new TestTelephonyConnection(); 723 Phone slot0Phone = c.getPhone(); 724 when(slot0Phone.getPhoneId()).thenReturn(SLOT_0_PHONE_ID); 725 Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE, 726 false /*isEmergencyOnly*/); 727 setPhonesDialConnection(slot1Phone, c.getOriginalConnection()); 728 c.setAddress(Uri.parse("tel:+16505551212"), TelecomManager.PRESENTATION_ALLOWED); 729 List<Phone> phones = new ArrayList<>(2); 730 phones.add(slot0Phone); 731 phones.add(slot1Phone); 732 setPhones(phones); 733 734 // First Permanent failure 735 mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/); 736 // Set the Phone to the new phone that was just used to dial. 737 c.setMockPhone(slot1Phone); 738 // The cache should only contain one phone 739 assertEquals(1, mTestConnectionService.mEmergencyRetryCache.second.size()); 740 // Make sure slot 1 is next in the queue. 741 assertEquals(slot1Phone, mTestConnectionService.mEmergencyRetryCache.second.peek()); 742 // Second Permanent failure 743 mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/); 744 // The cache should be empty 745 assertEquals(true, mTestConnectionService.mEmergencyRetryCache.second.isEmpty()); 746 747 assertEquals(c.getState(), android.telecom.Connection.STATE_DISCONNECTED); 748 assertEquals(c.getDisconnectCause().getCode(), DisconnectCause.ERROR); 749 // We need to be notified in Telecom that the PhoneAccount has changed, because it was 750 // redialed on another slot 751 assertEquals(1, c.getNotifyPhoneAccountChangedCount()); 752 try { 753 verify(slot1Phone).dial(anyString(), any()); 754 verify(slot0Phone, never()).dial(anyString(), any()); 755 } catch (CallStateException e) { 756 // This shouldn't happen 757 fail(); 758 } 759 } 760 761 @Test 762 @SmallTest 763 public void testSuppServiceNotification() { 764 TestTelephonyConnection c = new TestTelephonyConnection(); 765 766 // We need to set the original connection to cause the supp service notification 767 // registration to occur. 768 Phone phone = c.getPhone(); 769 c.setOriginalConnection(c.getOriginalConnection()); 770 771 // When the registration occurs, we'll capture the handler and message so we can post our 772 // own messages to it. 773 ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class); 774 ArgumentCaptor<Integer> messageCaptor = ArgumentCaptor.forClass(Integer.class); 775 verify(phone).registerForSuppServiceNotification(handlerCaptor.capture(), 776 messageCaptor.capture(), any()); 777 Handler handler = handlerCaptor.getValue(); 778 int message = messageCaptor.getValue(); 779 780 // With the handler and message now known, we'll post a supp service notification. 781 AsyncResult result = getSuppServiceNotification( 782 SuppServiceNotification.NOTIFICATION_TYPE_CODE_1, 783 SuppServiceNotification.CODE_1_CALL_FORWARDED); 784 handler.obtainMessage(message, result).sendToTarget(); 785 waitForHandlerAction(handler, TIMEOUT_MS); 786 787 assertTrue(c.getLastConnectionEvents().contains(TelephonyManager.EVENT_CALL_FORWARDED)); 788 789 // With the handler and message now known, we'll post a supp service notification. 790 result = getSuppServiceNotification( 791 SuppServiceNotification.NOTIFICATION_TYPE_CODE_1, 792 SuppServiceNotification.CODE_1_CALL_IS_WAITING); 793 handler.obtainMessage(message, result).sendToTarget(); 794 waitForHandlerAction(handler, TIMEOUT_MS); 795 796 // We we want the 3rd event since the forwarding one above sends 2. 797 assertEquals(c.getLastConnectionEvents().get(2), 798 TelephonyManager.EVENT_SUPPLEMENTARY_SERVICE_NOTIFICATION); 799 Bundle extras = c.getLastConnectionEventExtras().get(2); 800 assertEquals(SuppServiceNotification.NOTIFICATION_TYPE_CODE_1, 801 extras.getInt(TelephonyManager.EXTRA_NOTIFICATION_TYPE)); 802 assertEquals(SuppServiceNotification.CODE_1_CALL_IS_WAITING, 803 extras.getInt(TelephonyManager.EXTRA_NOTIFICATION_CODE)); 804 } 805 806 private AsyncResult getSuppServiceNotification(int notificationType, int code) { 807 SuppServiceNotification notification = new SuppServiceNotification(); 808 notification.notificationType = notificationType; 809 notification.code = code; 810 return new AsyncResult(null, notification, null); 811 } 812 813 private Phone makeTestPhone(int phoneId, int serviceState, boolean isEmergencyOnly) { 814 Phone phone = mock(Phone.class); 815 ServiceState testServiceState = new ServiceState(); 816 testServiceState.setState(serviceState); 817 testServiceState.setEmergencyOnly(isEmergencyOnly); 818 when(phone.getServiceState()).thenReturn(testServiceState); 819 when(phone.getPhoneId()).thenReturn(phoneId); 820 return phone; 821 } 822 823 // Setup 2 SIM device 824 private void setupDeviceConfig(Phone slot0Phone, Phone slot1Phone, int defaultVoicePhoneId) { 825 when(mTelephonyManagerProxy.getPhoneCount()).thenReturn(2); 826 when(mSubscriptionManagerProxy.getDefaultVoicePhoneId()).thenReturn(defaultVoicePhoneId); 827 when(mPhoneFactoryProxy.getPhone(eq(SLOT_0_PHONE_ID))).thenReturn(slot0Phone); 828 when(mPhoneFactoryProxy.getPhone(eq(SLOT_1_PHONE_ID))).thenReturn(slot1Phone); 829 } 830 831 private void setPhoneRadioAccessFamily(Phone phone, int radioAccessFamily) { 832 when(phone.getRadioAccessFamily()).thenReturn(radioAccessFamily); 833 } 834 835 private void setPhoneSlotState(int slotId, int slotState) { 836 when(mSubscriptionManagerProxy.getSimStateForSlotIdx(slotId)).thenReturn(slotState); 837 } 838 839 private void setSlotHasIccCard(int slotId, boolean isInserted) { 840 when(mTelephonyManagerProxy.hasIccCard(slotId)).thenReturn(isInserted); 841 } 842 843 private void setDefaultPhone(Phone phone) { 844 when(mPhoneFactoryProxy.getDefaultPhone()).thenReturn(phone); 845 } 846 847 private void setPhones(List<Phone> phones) { 848 when(mPhoneFactoryProxy.getPhones()).thenReturn(phones.toArray(new Phone[phones.size()])); 849 } 850 851 private void setPhonesDialConnection(Phone phone, Connection c) { 852 try { 853 when(phone.dial(anyString(), any())).thenReturn(c); 854 } catch (CallStateException e) { 855 // this shouldn't happen 856 fail(); 857 } 858 } 859} 860