1 /* 2 * Copyright (C) 2022 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.domainselection; 18 19 import static android.telephony.DomainSelectionService.SELECTOR_TYPE_CALLING; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertFalse; 23 import static org.junit.Assert.assertTrue; 24 import static org.junit.Assert.fail; 25 import static org.mockito.Mockito.any; 26 import static org.mockito.Mockito.doNothing; 27 import static org.mockito.Mockito.doReturn; 28 29 import android.annotation.NonNull; 30 import android.content.Context; 31 import android.net.Uri; 32 import android.os.CancellationSignal; 33 import android.os.HandlerThread; 34 import android.os.Looper; 35 import android.os.PersistableBundle; 36 import android.telecom.PhoneAccount; 37 import android.telecom.TelecomManager; 38 import android.telephony.AccessNetworkConstants; 39 import android.telephony.CarrierConfigManager; 40 import android.telephony.DisconnectCause; 41 import android.telephony.DomainSelectionService; 42 import android.telephony.DomainSelector; 43 import android.telephony.EmergencyRegistrationResult; 44 import android.telephony.NetworkRegistrationInfo; 45 import android.telephony.ServiceState; 46 import android.telephony.SubscriptionManager; 47 import android.telephony.TransportSelectorCallback; 48 import android.telephony.WwanSelectorCallback; 49 import android.telephony.ims.ImsManager; 50 import android.telephony.ims.ImsMmTelManager; 51 import android.telephony.ims.ImsReasonInfo; 52 import android.testing.TestableLooper; 53 import android.util.Log; 54 55 import androidx.test.runner.AndroidJUnit4; 56 57 import com.android.internal.telephony.CallFailCause; 58 59 import org.junit.After; 60 import org.junit.Before; 61 import org.junit.Test; 62 import org.junit.runner.RunWith; 63 import org.mockito.Mock; 64 import org.mockito.MockitoAnnotations; 65 66 import java.util.List; 67 import java.util.function.Consumer; 68 69 /** 70 * Unit tests for DomainSelectorBase. 71 */ 72 @RunWith(AndroidJUnit4.class) 73 public class NormalCallDomainSelectorTest { 74 private static final String TAG = "NormalCallDomainSelectorTest"; 75 76 private static final int SELECTOR_TYPE_UT = 3; 77 private static final int SLOT_ID = 0; 78 private static final int SUB_ID_1 = 1; 79 private static final int SUB_ID_2 = 2; 80 private static final String TEST_CALLID = "01234"; 81 private static final Uri TEST_URI = Uri.fromParts(PhoneAccount.SCHEME_TEL, "123456789", null); 82 83 private HandlerThread mHandlerThread; 84 private NormalCallDomainSelector mNormalCallDomainSelector; 85 private TestableLooper mTestableLooper; 86 @Mock private Context mMockContext; 87 @Mock private CarrierConfigManager mMockCarrierConfigMgr; 88 @Mock private ImsManager mMockImsManager; 89 @Mock private ImsMmTelManager mMockMmTelManager; 90 @Mock private ImsStateTracker mMockImsStateTracker; 91 @Mock private DomainSelectorBase.DestroyListener mMockDestroyListener; 92 @Mock private TelecomManager mMockTelecomManager; 93 94 @Before setUp()95 public void setUp() throws Exception { 96 MockitoAnnotations.initMocks(this); 97 98 doReturn(Context.TELEPHONY_IMS_SERVICE).when(mMockContext) 99 .getSystemServiceName(ImsManager.class); 100 doReturn(mMockImsManager).when(mMockContext) 101 .getSystemService(Context.TELEPHONY_IMS_SERVICE); 102 103 doReturn(Context.CARRIER_CONFIG_SERVICE).when(mMockContext) 104 .getSystemServiceName(CarrierConfigManager.class); 105 doReturn(mMockCarrierConfigMgr).when(mMockContext) 106 .getSystemService(Context.CARRIER_CONFIG_SERVICE); 107 108 doReturn(Context.TELECOM_SERVICE).when(mMockContext) 109 .getSystemServiceName(TelecomManager.class); 110 doReturn(mMockTelecomManager).when(mMockContext) 111 .getSystemService(Context.TELECOM_SERVICE); 112 113 doReturn(mMockMmTelManager).when(mMockImsManager).getImsMmTelManager(SUB_ID_1); 114 doReturn(mMockMmTelManager).when(mMockImsManager).getImsMmTelManager(SUB_ID_2); 115 doNothing().when(mMockImsStateTracker).removeServiceStateListener(any()); 116 doNothing().when(mMockImsStateTracker).removeImsStateListener(any()); 117 doReturn(true).when(mMockImsStateTracker).isMmTelFeatureAvailable(); 118 119 // Set up the looper if it does not exist on the test thread. 120 if (Looper.myLooper() == null) { 121 Looper.prepare(); 122 } 123 124 mHandlerThread = new HandlerThread( 125 NormalCallDomainSelectorTest.class.getSimpleName()); 126 mHandlerThread.start(); 127 128 mNormalCallDomainSelector = new NormalCallDomainSelector(mMockContext, SLOT_ID, SUB_ID_1, 129 mHandlerThread.getLooper(), mMockImsStateTracker, mMockDestroyListener); 130 131 try { 132 setUpTestableLooper(); 133 } catch (Exception e) { 134 fail(e.toString()); 135 } 136 } 137 138 @After tearDown()139 public void tearDown() throws Exception { 140 if (mHandlerThread != null) { 141 mHandlerThread.quit(); 142 } 143 144 if (mTestableLooper != null) { 145 mTestableLooper.destroy(); 146 mTestableLooper = null; 147 } 148 } 149 setUpTestableLooper()150 private void setUpTestableLooper() throws Exception { 151 mTestableLooper = new TestableLooper(mNormalCallDomainSelector.getLooper()); 152 } 153 processAllMessages()154 private void processAllMessages() { 155 Log.d(TAG, "processAllMessages - start"); 156 while (!mTestableLooper.getLooper().getQueue().isIdle()) { 157 mTestableLooper.processAllMessages(); 158 } 159 Log.d(TAG, "processAllMessages - end"); 160 } 161 initialize(ServiceState serviceState, boolean isImsRegistered, boolean isImsRegisteredOverWlan, boolean isImsVoiceCapable, boolean isImsVideoCapable)162 private void initialize(ServiceState serviceState, boolean isImsRegistered, 163 boolean isImsRegisteredOverWlan, boolean isImsVoiceCapable, 164 boolean isImsVideoCapable) { 165 if (serviceState != null) mNormalCallDomainSelector.onServiceStateUpdated(serviceState); 166 doReturn(isImsRegistered).when(mMockImsStateTracker).isImsStateReady(); 167 doReturn(isImsRegistered).when(mMockImsStateTracker).isImsRegistered(); 168 doReturn(isImsVoiceCapable).when(mMockImsStateTracker).isImsVoiceCapable(); 169 doReturn(isImsVideoCapable).when(mMockImsStateTracker).isImsVideoCapable(); 170 doReturn(isImsRegisteredOverWlan).when(mMockImsStateTracker).isImsRegisteredOverWlan(); 171 mNormalCallDomainSelector.onImsRegistrationStateChanged(); 172 mNormalCallDomainSelector.onImsMmTelCapabilitiesChanged(); 173 } 174 175 @Test testInit()176 public void testInit() { 177 assertEquals(SLOT_ID, mNormalCallDomainSelector.getSlotId()); 178 assertEquals(SUB_ID_1, mNormalCallDomainSelector.getSubId()); 179 } 180 181 @Test testInitialState()182 public void testInitialState() { 183 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 184 mNormalCallDomainSelector.getSelectorState()); 185 } 186 187 @Test testDestroyedState()188 public void testDestroyedState() { 189 mNormalCallDomainSelector.destroy(); 190 191 assertEquals(NormalCallDomainSelector.SelectorState.DESTROYED, 192 mNormalCallDomainSelector.getSelectorState()); 193 } 194 195 @Test testDestroyedDuringActiveState()196 public void testDestroyedDuringActiveState() { 197 TestTransportSelectorCallback transportSelectorCallback = 198 new TestTransportSelectorCallback(mNormalCallDomainSelector); 199 200 DomainSelectionService.SelectionAttributes attributes = 201 new DomainSelectionService.SelectionAttributes.Builder( 202 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 203 .setAddress(TEST_URI) 204 .setCallId(TEST_CALLID) 205 .setEmergency(false) 206 .setVideoCall(true) 207 .setExitedFromAirplaneMode(false) 208 .build(); 209 210 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 211 212 assertEquals(NormalCallDomainSelector.SelectorState.ACTIVE, 213 mNormalCallDomainSelector.getSelectorState()); 214 215 mNormalCallDomainSelector.destroy(); 216 217 assertEquals(NormalCallDomainSelector.SelectorState.DESTROYED, 218 mNormalCallDomainSelector.getSelectorState()); 219 } 220 221 @Test testSelectDomainInputParams()222 public void testSelectDomainInputParams() { 223 TestTransportSelectorCallback transportSelectorCallback = 224 new TestTransportSelectorCallback(mNormalCallDomainSelector); 225 226 DomainSelectionService.SelectionAttributes attributes = 227 new DomainSelectionService.SelectionAttributes.Builder( 228 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 229 .setAddress(TEST_URI) 230 .setCallId(TEST_CALLID) 231 .setEmergency(false) 232 .setVideoCall(true) 233 .setExitedFromAirplaneMode(false) 234 .build(); 235 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 236 237 assertEquals(NormalCallDomainSelector.SelectorState.ACTIVE, 238 mNormalCallDomainSelector.getSelectorState()); 239 240 // Case 1: null inputs 241 try { 242 mNormalCallDomainSelector.selectDomain(null, null); 243 } catch (Exception e) { 244 fail("Invalid input params not handled." + e.getMessage()); 245 } 246 247 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 248 mNormalCallDomainSelector.getSelectorState()); 249 250 // Case 2: null TransportSelectorCallback 251 try { 252 mNormalCallDomainSelector.selectDomain(attributes, null); 253 } catch (Exception e) { 254 fail("Invalid params (SelectionAttributes) not handled." + e.getMessage()); 255 } 256 257 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 258 mNormalCallDomainSelector.getSelectorState()); 259 260 // Case 3: null SelectionAttributes 261 transportSelectorCallback.mSelectionTerminated = false; 262 try { 263 mNormalCallDomainSelector.selectDomain(null, transportSelectorCallback); 264 } catch (Exception e) { 265 fail("Invalid params (SelectionAttributes) not handled." + e.getMessage()); 266 } 267 268 assertTrue(transportSelectorCallback.mSelectionTerminated); 269 assertEquals(transportSelectorCallback.mCauseCode, DisconnectCause.OUTGOING_FAILURE); 270 assertEquals(NormalCallDomainSelector.SelectorState.DESTROYED, 271 mNormalCallDomainSelector.getSelectorState()); 272 273 // Case 4: Invalid Subscription-id 274 attributes = new DomainSelectionService.SelectionAttributes.Builder( 275 SLOT_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID, SELECTOR_TYPE_CALLING) 276 .setAddress(TEST_URI) 277 .setCallId(TEST_CALLID) 278 .setEmergency(false) 279 .setVideoCall(true) 280 .setExitedFromAirplaneMode(false) 281 .build(); 282 try { 283 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 284 } catch (Exception e) { 285 fail("Invalid params (SelectionAttributes) not handled." + e.getMessage()); 286 } 287 288 assertTrue(transportSelectorCallback.mSelectionTerminated); 289 assertEquals(transportSelectorCallback.mCauseCode, DisconnectCause.OUTGOING_FAILURE); 290 assertEquals(NormalCallDomainSelector.SelectorState.DESTROYED, 291 mNormalCallDomainSelector.getSelectorState()); 292 293 // Case 5: Invalid SELECTOR_TYPE 294 attributes = 295 new DomainSelectionService.SelectionAttributes.Builder( 296 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_UT) 297 .setAddress(TEST_URI) 298 .setCallId(TEST_CALLID) 299 .setEmergency(false) 300 .setVideoCall(true) 301 .setExitedFromAirplaneMode(false) 302 .build(); 303 try { 304 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 305 } catch (Exception e) { 306 fail("Invalid params (SelectionAttributes) not handled." + e.getMessage()); 307 } 308 309 assertTrue(transportSelectorCallback.mSelectionTerminated); 310 assertEquals(transportSelectorCallback.mCauseCode, DisconnectCause.OUTGOING_FAILURE); 311 assertEquals(NormalCallDomainSelector.SelectorState.DESTROYED, 312 mNormalCallDomainSelector.getSelectorState()); 313 314 // Case 6: Emergency Call 315 attributes = new DomainSelectionService.SelectionAttributes.Builder( 316 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 317 .setAddress(TEST_URI) 318 .setCallId(TEST_CALLID) 319 .setEmergency(true) 320 .setVideoCall(true) 321 .setExitedFromAirplaneMode(false) 322 .build(); 323 try { 324 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 325 } catch (Exception e) { 326 fail("Invalid params (SelectionAttributes) not handled." + e.getMessage()); 327 } 328 329 assertTrue(transportSelectorCallback.mSelectionTerminated); 330 assertEquals(transportSelectorCallback.mCauseCode, DisconnectCause.OUTGOING_FAILURE); 331 assertEquals(NormalCallDomainSelector.SelectorState.DESTROYED, 332 mNormalCallDomainSelector.getSelectorState()); 333 } 334 335 @Test testOutOfService()336 public void testOutOfService() { 337 final TestTransportSelectorCallback transportSelectorCallback = 338 new TestTransportSelectorCallback(mNormalCallDomainSelector); 339 340 DomainSelectionService.SelectionAttributes attributes = 341 new DomainSelectionService.SelectionAttributes.Builder( 342 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 343 .setAddress(TEST_URI) 344 .setCallId(TEST_CALLID) 345 .setEmergency(false) 346 .setVideoCall(true) 347 .setExitedFromAirplaneMode(false) 348 .build(); 349 350 ServiceState serviceState = new ServiceState(); 351 serviceState.setStateOutOfService(); 352 initialize(serviceState, false, false, false, false); 353 354 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 355 356 357 processAllMessages(); 358 assertTrue(transportSelectorCallback.mSelectionTerminated); 359 assertEquals(DisconnectCause.OUT_OF_SERVICE, transportSelectorCallback.mCauseCode); 360 361 assertEquals(NormalCallDomainSelector.SelectorState.DESTROYED, 362 mNormalCallDomainSelector.getSelectorState()); 363 } 364 365 @Test testDomainSelection()366 public void testDomainSelection() { 367 final TestTransportSelectorCallback transportSelectorCallback = 368 new TestTransportSelectorCallback(mNormalCallDomainSelector); 369 370 final ServiceState serviceState = new ServiceState(); 371 serviceState.setState(ServiceState.STATE_IN_SERVICE); 372 initialize(serviceState, true, true, true, true); 373 transportSelectorCallback.reset(); 374 DomainSelectionService.SelectionAttributes attributes = 375 new DomainSelectionService.SelectionAttributes.Builder( 376 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 377 .setAddress(TEST_URI) 378 .setCallId(TEST_CALLID) 379 .setEmergency(false) 380 .setVideoCall(false) 381 .setExitedFromAirplaneMode(false) 382 .build(); 383 384 // Case 1: WLAN 385 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 386 387 processAllMessages(); 388 assertTrue(transportSelectorCallback.mWlanSelected); 389 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 390 mNormalCallDomainSelector.getSelectorState()); 391 392 // Case 2: 5G 393 serviceState.setState(ServiceState.STATE_IN_SERVICE); 394 initialize(serviceState, true, false, true, true); 395 transportSelectorCallback.reset(); 396 attributes = new DomainSelectionService.SelectionAttributes.Builder( 397 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 398 .setAddress(TEST_URI) 399 .setCallId(TEST_CALLID) 400 .setEmergency(false) 401 .setVideoCall(false) 402 .setExitedFromAirplaneMode(false) 403 .build(); 404 405 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 406 407 processAllMessages(); 408 assertTrue(transportSelectorCallback.mWwanSelected); 409 assertEquals(NetworkRegistrationInfo.DOMAIN_PS, transportSelectorCallback.mSelectedDomain); 410 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 411 mNormalCallDomainSelector.getSelectorState()); 412 413 414 // Case 3: PS -> CS redial 415 final ImsReasonInfo imsReasonInfoCsRetry = new ImsReasonInfo( 416 ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED, 0, null); 417 transportSelectorCallback.reset(); 418 attributes = new DomainSelectionService.SelectionAttributes.Builder( 419 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 420 .setAddress(TEST_URI) 421 .setCallId(TEST_CALLID) 422 .setEmergency(false) 423 .setVideoCall(false) 424 .setExitedFromAirplaneMode(false) 425 .setPsDisconnectCause(imsReasonInfoCsRetry) 426 .build(); 427 428 mNormalCallDomainSelector.reselectDomain(attributes); 429 430 processAllMessages(); 431 assertEquals(transportSelectorCallback.mSelectedDomain, NetworkRegistrationInfo.DOMAIN_CS); 432 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 433 mNormalCallDomainSelector.getSelectorState()); 434 435 // Case 4: CS call 436 transportSelectorCallback.reset(); 437 initialize(serviceState, false, false, false, false); 438 NetworkRegistrationInfo nwRegistrationInfo = new NetworkRegistrationInfo( 439 NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN, 440 NetworkRegistrationInfo.REGISTRATION_STATE_HOME, 441 AccessNetworkConstants.AccessNetworkType.UTRAN, 0, false, 442 null, null, null, false, 0, 0, 0); 443 serviceState.addNetworkRegistrationInfo(nwRegistrationInfo); 444 attributes = new DomainSelectionService.SelectionAttributes.Builder( 445 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 446 .setAddress(TEST_URI) 447 .setCallId(TEST_CALLID) 448 .setEmergency(false) 449 .setVideoCall(false) 450 .setExitedFromAirplaneMode(false) 451 .build(); 452 453 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 454 455 processAllMessages(); 456 assertEquals(transportSelectorCallback.mSelectedDomain, NetworkRegistrationInfo.DOMAIN_CS); 457 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 458 mNormalCallDomainSelector.getSelectorState()); 459 460 //Case 5: Backup calling 461 serviceState.setStateOutOfService(); 462 transportSelectorCallback.reset(); 463 attributes = new DomainSelectionService.SelectionAttributes.Builder( 464 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 465 .setAddress(TEST_URI) 466 .setCallId(TEST_CALLID) 467 .setEmergency(false) 468 .setVideoCall(false) 469 .setExitedFromAirplaneMode(false) 470 .setPsDisconnectCause(imsReasonInfoCsRetry) 471 .build(); 472 initialize(serviceState, true, true, true, true); 473 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 474 475 processAllMessages(); 476 assertTrue(transportSelectorCallback.mWlanSelected); 477 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 478 mNormalCallDomainSelector.getSelectorState()); 479 } 480 481 @Test testWPSCallDomainSelection()482 public void testWPSCallDomainSelection() { 483 TestTransportSelectorCallback transportSelectorCallback = 484 new TestTransportSelectorCallback(mNormalCallDomainSelector); 485 DomainSelectionService.SelectionAttributes attributes = 486 new DomainSelectionService.SelectionAttributes.Builder( 487 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 488 .setAddress(Uri.fromParts(PhoneAccount.SCHEME_TEL, "*272121", null)) 489 .setCallId(TEST_CALLID) 490 .setEmergency(false) 491 .setVideoCall(false) 492 .setExitedFromAirplaneMode(false) 493 .build(); 494 495 //Case 1: WPS not supported by IMS 496 PersistableBundle config = new PersistableBundle(); 497 config.putBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL, false); 498 doReturn(config).when(mMockCarrierConfigMgr).getConfigForSubId(SUB_ID_1, 499 new String[]{CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL}); 500 501 ServiceState serviceState = new ServiceState(); 502 serviceState.setState(ServiceState.STATE_IN_SERVICE); 503 initialize(serviceState, true, true, true, true); 504 505 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 506 507 processAllMessages(); 508 assertTrue(transportSelectorCallback.mWwanSelected); 509 assertEquals(transportSelectorCallback.mSelectedDomain, NetworkRegistrationInfo.DOMAIN_CS); 510 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 511 mNormalCallDomainSelector.getSelectorState()); 512 513 //Case 2: WPS supported by IMS and WLAN registered 514 transportSelectorCallback.reset(); 515 config.putBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL, true); 516 serviceState.setState(ServiceState.STATE_IN_SERVICE); 517 initialize(serviceState, true, true, true, true); 518 519 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 520 521 processAllMessages(); 522 assertTrue(transportSelectorCallback.mWlanSelected); 523 assertEquals(mNormalCallDomainSelector.getSelectorState(), 524 NormalCallDomainSelector.SelectorState.INACTIVE); 525 526 //Case 2: WPS supported by IMS and LTE registered 527 transportSelectorCallback.reset(); 528 config.putBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL, true); 529 serviceState.setState(ServiceState.STATE_IN_SERVICE); 530 initialize(serviceState, true, false, true, true); 531 532 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 533 534 processAllMessages(); 535 assertEquals(transportSelectorCallback.mSelectedDomain, NetworkRegistrationInfo.DOMAIN_PS); 536 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 537 mNormalCallDomainSelector.getSelectorState()); 538 } 539 540 @Test testTtyCallDomainSelection()541 public void testTtyCallDomainSelection() { 542 TestTransportSelectorCallback transportSelectorCallback = 543 new TestTransportSelectorCallback(mNormalCallDomainSelector); 544 DomainSelectionService.SelectionAttributes attributes = 545 new DomainSelectionService.SelectionAttributes.Builder( 546 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 547 .setAddress(TEST_URI) 548 .setCallId(TEST_CALLID) 549 .setEmergency(false) 550 .setVideoCall(false) 551 .setExitedFromAirplaneMode(false) 552 .build(); 553 554 //Case 1: TTY not supported by IMS and TTY enabled 555 doReturn(TelecomManager.TTY_MODE_FULL).when(mMockTelecomManager).getCurrentTtyMode(); 556 PersistableBundle config = new PersistableBundle(); 557 config.putBoolean(CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, false); 558 doReturn(config).when(mMockCarrierConfigMgr).getConfigForSubId(SUB_ID_1, 559 new String[]{CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL}); 560 561 ServiceState serviceState = new ServiceState(); 562 serviceState.setState(ServiceState.STATE_IN_SERVICE); 563 initialize(serviceState, true, false, true, true); 564 565 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 566 567 processAllMessages(); 568 assertTrue(transportSelectorCallback.mWwanSelected); 569 assertEquals(transportSelectorCallback.mSelectedDomain, NetworkRegistrationInfo.DOMAIN_CS); 570 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 571 mNormalCallDomainSelector.getSelectorState()); 572 573 //Case 2: TTY supported by IMS and TTY enabled 574 transportSelectorCallback.reset(); 575 config.putBoolean(CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, true); 576 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 577 578 processAllMessages(); 579 assertEquals(transportSelectorCallback.mSelectedDomain, NetworkRegistrationInfo.DOMAIN_PS); 580 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 581 mNormalCallDomainSelector.getSelectorState()); 582 583 //Case 3: TTY supported by IMS and TTY disabled 584 transportSelectorCallback.reset(); 585 doReturn(TelecomManager.TTY_MODE_OFF).when(mMockTelecomManager).getCurrentTtyMode(); 586 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 587 588 processAllMessages(); 589 assertEquals(transportSelectorCallback.mSelectedDomain, NetworkRegistrationInfo.DOMAIN_PS); 590 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 591 mNormalCallDomainSelector.getSelectorState()); 592 } 593 594 @Test testEmcCsFailureAndPsRedial()595 public void testEmcCsFailureAndPsRedial() { 596 final TestTransportSelectorCallback transportSelectorCallback = 597 new TestTransportSelectorCallback(mNormalCallDomainSelector); 598 599 final ServiceState serviceState = new ServiceState(); 600 601 // dial CS call 602 serviceState.setState(ServiceState.STATE_IN_SERVICE); 603 initialize(serviceState, false, false, false, false); 604 NetworkRegistrationInfo nwRegistrationInfo = new NetworkRegistrationInfo( 605 NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN, 606 NetworkRegistrationInfo.REGISTRATION_STATE_HOME, 607 AccessNetworkConstants.AccessNetworkType.UTRAN, 0, false, 608 null, null, null, false, 0, 0, 0); 609 serviceState.addNetworkRegistrationInfo(nwRegistrationInfo); 610 DomainSelectionService.SelectionAttributes attributes = 611 new DomainSelectionService.SelectionAttributes.Builder( 612 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 613 .setAddress(TEST_URI) 614 .setCallId(TEST_CALLID) 615 .setEmergency(false) 616 .setVideoCall(false) 617 .setExitedFromAirplaneMode(false) 618 .build(); 619 620 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 621 622 processAllMessages(); 623 assertEquals(transportSelectorCallback.mSelectedDomain, NetworkRegistrationInfo.DOMAIN_CS); 624 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 625 mNormalCallDomainSelector.getSelectorState()); 626 627 // EMC_REDIAL_ON_IMS 628 transportSelectorCallback.reset(); 629 serviceState.setState(ServiceState.STATE_IN_SERVICE); 630 initialize(serviceState, true, false, true, false); 631 attributes = new DomainSelectionService.SelectionAttributes.Builder( 632 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 633 .setAddress(TEST_URI) 634 .setCallId(TEST_CALLID) 635 .setEmergency(false) 636 .setVideoCall(false) 637 .setExitedFromAirplaneMode(false) 638 .setCsDisconnectCause(CallFailCause.EMC_REDIAL_ON_IMS) 639 .build(); 640 641 mNormalCallDomainSelector.reselectDomain(attributes); 642 643 processAllMessages(); 644 assertTrue(transportSelectorCallback.mWwanSelected); 645 assertEquals(NetworkRegistrationInfo.DOMAIN_PS, transportSelectorCallback.mSelectedDomain); 646 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 647 mNormalCallDomainSelector.getSelectorState()); 648 649 // EMC_REDIAL_ON_VOWIFI 650 transportSelectorCallback.reset(); 651 initialize(serviceState, true, true, true, false); 652 attributes = new DomainSelectionService.SelectionAttributes.Builder( 653 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 654 .setAddress(TEST_URI) 655 .setCallId(TEST_CALLID) 656 .setEmergency(false) 657 .setVideoCall(false) 658 .setExitedFromAirplaneMode(false) 659 .setCsDisconnectCause(CallFailCause.EMC_REDIAL_ON_VOWIFI) 660 .build(); 661 662 mNormalCallDomainSelector.reselectDomain(attributes); 663 664 processAllMessages(); 665 assertTrue(transportSelectorCallback.mWlanSelected); 666 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 667 mNormalCallDomainSelector.getSelectorState()); 668 } 669 670 @Test testEmcPsFailureAndCsRedial()671 public void testEmcPsFailureAndCsRedial() { 672 final TestTransportSelectorCallback transportSelectorCallback = 673 new TestTransportSelectorCallback(mNormalCallDomainSelector); 674 675 final ServiceState serviceState = new ServiceState(); 676 677 // dial PS call with APN-ON 678 serviceState.setStateOutOfService(); 679 initialize(serviceState, true, true, true, false); 680 DomainSelectionService.SelectionAttributes attributes = 681 new DomainSelectionService.SelectionAttributes.Builder( 682 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 683 .setAddress(TEST_URI) 684 .setCallId(TEST_CALLID) 685 .setEmergency(false) 686 .setVideoCall(false) 687 .setExitedFromAirplaneMode(true) 688 .build(); 689 690 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 691 692 processAllMessages(); 693 assertTrue(transportSelectorCallback.mWlanSelected); 694 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 695 mNormalCallDomainSelector.getSelectorState()); 696 697 // CODE_LOCAL_CALL_CS_RETRY_REQUIRED when ServiceState is OOS 698 final ImsReasonInfo imsReasonInfoCsRetry = new ImsReasonInfo( 699 ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED, 0, null); 700 transportSelectorCallback.reset(); 701 702 attributes = new DomainSelectionService.SelectionAttributes.Builder( 703 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 704 .setAddress(TEST_URI) 705 .setCallId(TEST_CALLID) 706 .setEmergency(false) 707 .setVideoCall(false) 708 .setExitedFromAirplaneMode(true) 709 .setPsDisconnectCause(imsReasonInfoCsRetry) 710 .build(); 711 712 mNormalCallDomainSelector.reselectDomain(attributes); 713 714 processAllMessages(); 715 assertEquals(NetworkRegistrationInfo.DOMAIN_CS, transportSelectorCallback.mSelectedDomain); 716 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 717 mNormalCallDomainSelector.getSelectorState()); 718 } 719 720 @Test testImsRegistrationStateTimeoutMessage()721 public void testImsRegistrationStateTimeoutMessage() { 722 final TestTransportSelectorCallback transportSelectorCallback = 723 new TestTransportSelectorCallback(mNormalCallDomainSelector); 724 725 final ServiceState serviceState = new ServiceState(); 726 serviceState.setState(ServiceState.STATE_IN_SERVICE); 727 mNormalCallDomainSelector.onServiceStateUpdated(serviceState); 728 doReturn(true).when(mMockImsStateTracker).isImsStateReady(); 729 doReturn(true).when(mMockImsStateTracker).isImsRegistered(); 730 doReturn(true).when(mMockImsStateTracker).isImsVoiceCapable(); 731 doReturn(false).when(mMockImsStateTracker).isImsVideoCapable(); 732 doReturn(true).when(mMockImsStateTracker).isImsRegisteredOverWlan(); 733 734 DomainSelectionService.SelectionAttributes attributes = 735 new DomainSelectionService.SelectionAttributes.Builder( 736 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 737 .setAddress(TEST_URI) 738 .setCallId(TEST_CALLID) 739 .setEmergency(false) 740 .setVideoCall(false) 741 .setExitedFromAirplaneMode(false) 742 .build(); 743 744 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 745 assertTrue(mNormalCallDomainSelector.hasMessages( 746 NormalCallDomainSelector.MSG_WAIT_FOR_IMS_STATE_TIMEOUT)); 747 748 mNormalCallDomainSelector.onImsRegistrationStateChanged(); 749 mNormalCallDomainSelector.onImsMmTelCapabilitiesChanged(); 750 processAllMessages(); 751 752 assertFalse(mNormalCallDomainSelector.hasMessages( 753 NormalCallDomainSelector.MSG_WAIT_FOR_IMS_STATE_TIMEOUT)); 754 assertTrue(transportSelectorCallback.mWlanSelected); 755 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 756 mNormalCallDomainSelector.getSelectorState()); 757 } 758 759 @Test testImsRegistrationStateTimeoutHandler()760 public void testImsRegistrationStateTimeoutHandler() { 761 final TestTransportSelectorCallback transportSelectorCallback = 762 new TestTransportSelectorCallback(mNormalCallDomainSelector); 763 764 final ServiceState serviceState = new ServiceState(); 765 serviceState.setState(ServiceState.STATE_IN_SERVICE); 766 mNormalCallDomainSelector.onServiceStateUpdated(serviceState); 767 doReturn(true).when(mMockImsStateTracker).isImsStateReady(); 768 doReturn(false).when(mMockImsStateTracker).isImsRegistered(); 769 doReturn(true).when(mMockImsStateTracker).isImsVoiceCapable(); 770 doReturn(false).when(mMockImsStateTracker).isImsVideoCapable(); 771 doReturn(true).when(mMockImsStateTracker).isImsRegisteredOverWlan(); 772 773 DomainSelectionService.SelectionAttributes attributes = 774 new DomainSelectionService.SelectionAttributes.Builder( 775 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 776 .setAddress(TEST_URI) 777 .setCallId(TEST_CALLID) 778 .setEmergency(false) 779 .setVideoCall(false) 780 .setExitedFromAirplaneMode(false) 781 .build(); 782 783 mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback); 784 assertTrue(mNormalCallDomainSelector.hasMessages( 785 NormalCallDomainSelector.MSG_WAIT_FOR_IMS_STATE_TIMEOUT)); 786 787 mTestableLooper.moveTimeForward( 788 NormalCallDomainSelector.WAIT_FOR_IMS_STATE_TIMEOUT_MS + 10); 789 processAllMessages(); 790 791 assertEquals(transportSelectorCallback.mSelectedDomain, NetworkRegistrationInfo.DOMAIN_CS); 792 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 793 mNormalCallDomainSelector.getSelectorState()); 794 } 795 796 @Test testReselectDomainNoTimeoutMessage()797 public void testReselectDomainNoTimeoutMessage() { 798 final TestTransportSelectorCallback transportSelectorCallback = 799 new TestTransportSelectorCallback(mNormalCallDomainSelector); 800 801 DomainSelectionService.SelectionAttributes attributes = 802 new DomainSelectionService.SelectionAttributes.Builder( 803 SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING) 804 .setAddress(TEST_URI) 805 .setCallId(TEST_CALLID) 806 .setEmergency(false) 807 .setVideoCall(false) 808 .setExitedFromAirplaneMode(false) 809 .build(); 810 811 mNormalCallDomainSelector.selectDomain(null, transportSelectorCallback); 812 mNormalCallDomainSelector.reselectDomain(attributes); 813 assertFalse(mNormalCallDomainSelector.hasMessages( 814 NormalCallDomainSelector.MSG_WAIT_FOR_IMS_STATE_TIMEOUT)); 815 } 816 817 static class TestTransportSelectorCallback implements TransportSelectorCallback, 818 WwanSelectorCallback { 819 public boolean mCreated; 820 public boolean mWlanSelected; 821 public boolean mWwanSelected; 822 public boolean mSelectionTerminated; 823 public boolean mDomainSelected; 824 int mCauseCode; 825 int mSelectedDomain; 826 NormalCallDomainSelector mNormalCallDomainSelector; 827 TestTransportSelectorCallback(NormalCallDomainSelector normalCallDomainSelector)828 TestTransportSelectorCallback(NormalCallDomainSelector normalCallDomainSelector) { 829 mNormalCallDomainSelector = normalCallDomainSelector; 830 mCauseCode = DisconnectCause.NOT_VALID; 831 } 832 833 @Override onCreated(DomainSelector selector)834 public synchronized void onCreated(DomainSelector selector) { 835 Log.d(TAG, "onCreated"); 836 mCreated = true; 837 838 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 839 mNormalCallDomainSelector.getSelectorState()); 840 } 841 842 @Override onWlanSelected(boolean useEmergencyPdn)843 public synchronized void onWlanSelected(boolean useEmergencyPdn) { 844 Log.d(TAG, "onWlanSelected"); 845 mWlanSelected = true; 846 } 847 848 @Override onWwanSelected(final Consumer<WwanSelectorCallback> consumer)849 public void onWwanSelected(final Consumer<WwanSelectorCallback> consumer) { 850 Log.d(TAG, "onWwanSelected"); 851 mWwanSelected = true; 852 consumer.accept(this); 853 } 854 855 @Override onSelectionTerminated(int cause)856 public synchronized void onSelectionTerminated(int cause) { 857 Log.i(TAG, "onSelectionTerminated - called"); 858 mCauseCode = cause; 859 mSelectionTerminated = true; 860 861 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 862 mNormalCallDomainSelector.getSelectorState()); 863 864 notifyAll(); 865 } 866 867 @Override onRequestEmergencyNetworkScan(@onNull List<Integer> preferredNetworks, int scanType, boolean resetScan, @NonNull CancellationSignal signal, @NonNull Consumer<EmergencyRegistrationResult> consumer)868 public void onRequestEmergencyNetworkScan(@NonNull List<Integer> preferredNetworks, 869 int scanType, 870 boolean resetScan, 871 @NonNull CancellationSignal signal, 872 @NonNull Consumer<EmergencyRegistrationResult> consumer) { 873 Log.i(TAG, "onRequestEmergencyNetworkScan - called"); 874 875 } 876 onDomainSelected(@etworkRegistrationInfo.Domain int domain, boolean useEmergencyPdn)877 public synchronized void onDomainSelected(@NetworkRegistrationInfo.Domain int domain, 878 boolean useEmergencyPdn) { 879 Log.i(TAG, "onDomainSelected - called"); 880 mSelectedDomain = domain; 881 mDomainSelected = true; 882 mWwanSelected = true; 883 884 assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE, 885 mNormalCallDomainSelector.getSelectorState()); 886 887 notifyAll(); 888 } reset()889 public void reset() { 890 mCreated = false; 891 mWlanSelected = false; 892 mWwanSelected = false; 893 mSelectionTerminated = false; 894 mDomainSelected = false; 895 mCauseCode = DisconnectCause.NOT_VALID; 896 mSelectedDomain = NetworkRegistrationInfo.DOMAIN_UNKNOWN; 897 } 898 } 899 } 900