• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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