• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.CarrierConfigManager.ImsEmergency.KEY_CROSS_STACK_REDIAL_TIMER_SEC_INT;
20 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT;
21 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_START_QUICK_CROSS_STACK_REDIAL_TIMER_WHEN_REGISTERED_BOOL;
22 import static android.telephony.CarrierConfigManager.ImsEmergency.REDIAL_TIMER_DISABLED;
23 import static android.telephony.PreciseDisconnectCause.EMERGENCY_PERM_FAILURE;
24 import static android.telephony.PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE;
25 
26 import static com.android.services.telephony.domainselection.CrossSimRedialingController.MSG_CROSS_STACK_TIMEOUT;
27 import static com.android.services.telephony.domainselection.CrossSimRedialingController.MSG_QUICK_CROSS_STACK_TIMEOUT;
28 
29 import static junit.framework.Assert.assertFalse;
30 import static junit.framework.Assert.assertTrue;
31 
32 import static org.mockito.ArgumentMatchers.anyInt;
33 import static org.mockito.ArgumentMatchers.anyString;
34 import static org.mockito.Mockito.doReturn;
35 import static org.mockito.Mockito.times;
36 import static org.mockito.Mockito.verify;
37 import static org.mockito.Mockito.when;
38 
39 import android.content.Context;
40 import android.os.HandlerThread;
41 import android.os.Looper;
42 import android.os.PersistableBundle;
43 import android.telephony.CarrierConfigManager;
44 import android.telephony.TelephonyManager;
45 import android.testing.TestableLooper;
46 import android.util.Log;
47 
48 import com.android.TestContext;
49 
50 import org.junit.After;
51 import org.junit.Before;
52 import org.junit.Test;
53 import org.mockito.ArgumentMatchers;
54 import org.mockito.Mock;
55 import org.mockito.MockitoAnnotations;
56 
57 /**
58  * Unit tests for CrossSimRedialingController
59  */
60 public class CrossSimRedialingControllerTest {
61     private static final String TAG = "CrossSimRedialingControllerTest";
62 
63     private static final int SLOT_0 = 0;
64     private static final int SLOT_1 = 1;
65 
66     private static final String TELECOM_CALL_ID1 = "TC1";
67     private static final String TEST_EMERGENCY_NUMBER = "911";
68 
69     @Mock private CarrierConfigManager mCarrierConfigManager;
70     @Mock private TelephonyManager mTelephonyManager;
71     @Mock private EmergencyCallDomainSelector mEcds;
72     @Mock private CrossSimRedialingController.EmergencyNumberHelper mEmergencyNumberHelper;
73 
74     private Context mContext;
75 
76     private HandlerThread mHandlerThread;
77     private TestableLooper mLooper;
78     private CrossSimRedialingController mCsrController;
79 
80     @Before
setUp()81     public void setUp() throws Exception {
82         MockitoAnnotations.initMocks(this);
83         mContext = new TestContext() {
84             @Override
85             public String getSystemServiceName(Class<?> serviceClass) {
86                 if (serviceClass == TelephonyManager.class) {
87                     return Context.TELEPHONY_SERVICE;
88                 } else if (serviceClass == CarrierConfigManager.class) {
89                     return Context.CARRIER_CONFIG_SERVICE;
90                 }
91                 return super.getSystemServiceName(serviceClass);
92             }
93 
94             @Override
95             public String getOpPackageName() {
96                 return "";
97             }
98         };
99 
100         if (Looper.myLooper() == null) {
101             Looper.prepare();
102         }
103 
104         mHandlerThread = new HandlerThread("CrossSimRedialingControllerTest");
105         mHandlerThread.start();
106 
107         try {
108             mLooper = new TestableLooper(mHandlerThread.getLooper());
109         } catch (Exception e) {
110             logd("Unable to create looper from handler.");
111         }
112 
113         mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
114         when(mTelephonyManager.createForSubscriptionId(anyInt()))
115                 .thenReturn(mTelephonyManager);
116         when(mTelephonyManager.getNetworkCountryIso()).thenReturn("");
117         doReturn(2).when(mTelephonyManager).getActiveModemCount();
118         doReturn(TelephonyManager.SIM_STATE_READY)
119                 .when(mTelephonyManager).getSimState(anyInt());
120 
121         mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
122         doReturn(getDefaultPersistableBundle()).when(mCarrierConfigManager)
123                 .getConfigForSubId(anyInt(), ArgumentMatchers.<String>any());
124 
125         doReturn(true).when(mEmergencyNumberHelper).isEmergencyNumber(anyInt(), anyString());
126 
127         doReturn(SLOT_0).when(mEcds).getSlotId();
128     }
129 
130     @After
tearDown()131     public void tearDown() throws Exception {
132         if (mCsrController != null) {
133             mCsrController.destroy();
134             mCsrController = null;
135         }
136 
137         if (mLooper != null) {
138             mLooper.destroy();
139             mLooper = null;
140         }
141     }
142 
143     @Test
testDefaultStartTimerInService()144     public void testDefaultStartTimerInService() throws Exception {
145         createController();
146 
147         boolean inService = true;
148         boolean inRoaming = false;
149         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
150                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
151 
152         assertFalse(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
153         assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
154 
155         mCsrController.sendEmptyMessage(MSG_CROSS_STACK_TIMEOUT);
156         processAllMessages();
157 
158         verify(mEcds).notifyCrossStackTimerExpired();
159     }
160 
161     @Test
testDefaultStartTimerInServiceRoaming()162     public void testDefaultStartTimerInServiceRoaming() throws Exception {
163         createController();
164 
165         boolean inService = true;
166         boolean inRoaming = true;
167         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
168                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
169 
170         assertFalse(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
171         assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
172     }
173 
174     @Test
testDefaultStartTimerOutOfService()175     public void testDefaultStartTimerOutOfService() throws Exception {
176         createController();
177 
178         boolean inService = false;
179         boolean inRoaming = false;
180         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
181                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
182 
183         assertFalse(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
184         assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
185     }
186 
187     @Test
testDefaultStartTimerOutOfServiceRoaming()188     public void testDefaultStartTimerOutOfServiceRoaming() throws Exception {
189         createController();
190 
191         boolean inService = false;
192         boolean inRoaming = true;
193         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
194                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
195 
196         assertFalse(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
197         assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
198     }
199 
200     @Test
testQuickStartTimerInService()201     public void testQuickStartTimerInService() throws Exception {
202         PersistableBundle bundle = getDefaultPersistableBundle();
203         bundle.putInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT, 3);
204         doReturn(bundle).when(mCarrierConfigManager)
205                 .getConfigForSubId(anyInt(), ArgumentMatchers.<String>any());
206 
207         createController();
208 
209         boolean inService = true;
210         boolean inRoaming = false;
211         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
212                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
213 
214         assertTrue(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
215         assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
216 
217         mCsrController.sendEmptyMessage(MSG_QUICK_CROSS_STACK_TIMEOUT);
218         processAllMessages();
219 
220         verify(mEcds).notifyCrossStackTimerExpired();
221     }
222 
223     @Test
testQuickStartTimerInServiceRoaming()224     public void testQuickStartTimerInServiceRoaming() throws Exception {
225         PersistableBundle bundle = getDefaultPersistableBundle();
226         bundle.putInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT, 3);
227         doReturn(bundle).when(mCarrierConfigManager)
228                 .getConfigForSubId(anyInt(), ArgumentMatchers.<String>any());
229 
230         createController();
231 
232         boolean inService = true;
233         boolean inRoaming = true;
234         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
235                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
236 
237         assertFalse(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
238         assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
239     }
240 
241     @Test
testQuickStartTimerOutOfService()242     public void testQuickStartTimerOutOfService() throws Exception {
243         PersistableBundle bundle = getDefaultPersistableBundle();
244         bundle.putInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT, 3);
245         doReturn(bundle).when(mCarrierConfigManager)
246                 .getConfigForSubId(anyInt(), ArgumentMatchers.<String>any());
247 
248         createController();
249 
250         boolean inService = false;
251         boolean inRoaming = false;
252         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
253                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
254 
255         assertTrue(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
256         assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
257     }
258 
259     @Test
testQuickStartTimerOutOfServiceRoaming()260     public void testQuickStartTimerOutOfServiceRoaming() throws Exception {
261         PersistableBundle bundle = getDefaultPersistableBundle();
262         bundle.putInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT, 3);
263         doReturn(bundle).when(mCarrierConfigManager)
264                 .getConfigForSubId(anyInt(), ArgumentMatchers.<String>any());
265 
266         createController();
267 
268         boolean inService = false;
269         boolean inRoaming = true;
270         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
271                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
272 
273         assertFalse(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
274         assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
275     }
276 
277     @Test
testNoNormalStartTimerInService()278     public void testNoNormalStartTimerInService() throws Exception {
279         PersistableBundle bundle = getDefaultPersistableBundle();
280         bundle.putInt(KEY_CROSS_STACK_REDIAL_TIMER_SEC_INT, REDIAL_TIMER_DISABLED);
281         doReturn(bundle).when(mCarrierConfigManager)
282                 .getConfigForSubId(anyInt(), ArgumentMatchers.<String>any());
283 
284         createController();
285 
286         boolean inService = true;
287         boolean inRoaming = false;
288         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
289                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
290 
291         assertFalse(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
292         assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
293     }
294 
295     @Test
testQuickWhenInServiceStartTimerOutOfService()296     public void testQuickWhenInServiceStartTimerOutOfService() throws Exception {
297         PersistableBundle bundle = getDefaultPersistableBundle();
298         bundle.putInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT, 3);
299         bundle.putBoolean(KEY_START_QUICK_CROSS_STACK_REDIAL_TIMER_WHEN_REGISTERED_BOOL, true);
300         doReturn(bundle).when(mCarrierConfigManager)
301                 .getConfigForSubId(anyInt(), ArgumentMatchers.<String>any());
302 
303         createController();
304 
305         boolean inService = false;
306         boolean inRoaming = false;
307         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
308                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
309 
310         assertFalse(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
311         assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
312     }
313 
314     @Test
testQuickNoNormalStartTimerInService()315     public void testQuickNoNormalStartTimerInService() throws Exception {
316         PersistableBundle bundle = getDefaultPersistableBundle();
317         bundle.putInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT, 3);
318         bundle.putInt(KEY_CROSS_STACK_REDIAL_TIMER_SEC_INT, REDIAL_TIMER_DISABLED);
319         doReturn(bundle).when(mCarrierConfigManager)
320                 .getConfigForSubId(anyInt(), ArgumentMatchers.<String>any());
321 
322         createController();
323 
324         boolean inService = true;
325         boolean inRoaming = false;
326         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
327                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
328 
329         assertTrue(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
330         assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
331     }
332 
333     @Test
testDefaultSlot0ThenSlot1()334     public void testDefaultSlot0ThenSlot1() throws Exception {
335         createController();
336 
337         boolean inService = true;
338         boolean inRoaming = false;
339         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
340                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
341 
342         assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
343 
344         mCsrController.removeMessages(MSG_CROSS_STACK_TIMEOUT);
345         assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
346 
347         doReturn(SLOT_1).when(mEcds).getSlotId();
348         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
349                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
350 
351         assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
352     }
353 
354     @Test
testDefaultSlot0PermThenSlot1Timeout()355     public void testDefaultSlot0PermThenSlot1Timeout() throws Exception {
356         createController();
357 
358         boolean inService = true;
359         boolean inRoaming = false;
360         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
361                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
362 
363         assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
364 
365         mCsrController.notifyCallFailure(EMERGENCY_PERM_FAILURE);
366         mCsrController.stopTimer();
367         assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
368 
369         doReturn(SLOT_1).when(mEcds).getSlotId();
370         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
371                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
372 
373         assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
374 
375         mCsrController.sendEmptyMessage(MSG_CROSS_STACK_TIMEOUT);
376         processAllMessages();
377 
378         verify(mEcds, times(0)).notifyCrossStackTimerExpired();
379     }
380 
381     @Test
testDefaultSlot0TempThenSlot1Timeout()382     public void testDefaultSlot0TempThenSlot1Timeout() throws Exception {
383         createController();
384 
385         boolean inService = true;
386         boolean inRoaming = false;
387         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
388                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
389 
390         assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
391 
392         mCsrController.notifyCallFailure(EMERGENCY_TEMP_FAILURE);
393         mCsrController.stopTimer();
394         assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
395 
396         doReturn(SLOT_1).when(mEcds).getSlotId();
397         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
398                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
399 
400         assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
401 
402         mCsrController.sendEmptyMessage(MSG_CROSS_STACK_TIMEOUT);
403         processAllMessages();
404 
405         verify(mEcds).notifyCrossStackTimerExpired();
406     }
407 
408     @Test
testDefaultSlot0TempThenSlot1TimeoutNotEmergencyNumber()409     public void testDefaultSlot0TempThenSlot1TimeoutNotEmergencyNumber() throws Exception {
410         createController();
411 
412         boolean inService = true;
413         boolean inRoaming = false;
414         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
415                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
416 
417         assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
418 
419         mCsrController.notifyCallFailure(EMERGENCY_TEMP_FAILURE);
420         mCsrController.stopTimer();
421         assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
422 
423         doReturn(SLOT_1).when(mEcds).getSlotId();
424         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
425                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
426 
427         assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
428 
429         doReturn(false).when(mEmergencyNumberHelper).isEmergencyNumber(anyInt(), anyString());
430         mCsrController.sendEmptyMessage(MSG_CROSS_STACK_TIMEOUT);
431         processAllMessages();
432 
433         verify(mEcds, times(0)).notifyCrossStackTimerExpired();
434     }
435 
436     @Test
testDefaultSlot0TempThenSlot1TimeoutPinLocked()437     public void testDefaultSlot0TempThenSlot1TimeoutPinLocked() throws Exception {
438         createController();
439 
440         boolean inService = true;
441         boolean inRoaming = false;
442         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
443                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
444 
445         assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
446 
447         mCsrController.notifyCallFailure(EMERGENCY_TEMP_FAILURE);
448         mCsrController.stopTimer();
449         assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
450 
451         doReturn(SLOT_1).when(mEcds).getSlotId();
452         mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
453                 TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
454 
455         assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
456 
457         doReturn(TelephonyManager.SIM_STATE_PIN_REQUIRED)
458                 .when(mTelephonyManager).getSimState(anyInt());
459         mCsrController.sendEmptyMessage(MSG_CROSS_STACK_TIMEOUT);
460         processAllMessages();
461 
462         verify(mEcds, times(0)).notifyCrossStackTimerExpired();
463     }
464 
createController()465     private void createController() throws Exception {
466         mCsrController = new CrossSimRedialingController(mContext,
467                 mHandlerThread.getLooper(), mEmergencyNumberHelper);
468     }
469 
getDefaultPersistableBundle()470     private static PersistableBundle getDefaultPersistableBundle() {
471         return getPersistableBundle(0, 120, false);
472     }
473 
getPersistableBundle( int quickTimer, int timer, boolean startQuickInService)474     private static PersistableBundle getPersistableBundle(
475             int quickTimer, int timer, boolean startQuickInService) {
476         PersistableBundle bundle  = new PersistableBundle();
477         bundle.putInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT, quickTimer);
478         bundle.putInt(KEY_CROSS_STACK_REDIAL_TIMER_SEC_INT, timer);
479         bundle.putBoolean(KEY_START_QUICK_CROSS_STACK_REDIAL_TIMER_WHEN_REGISTERED_BOOL,
480                 startQuickInService);
481 
482         return bundle;
483     }
484 
processAllMessages()485     private void processAllMessages() {
486         while (!mLooper.getLooper().getQueue().isIdle()) {
487             mLooper.processAllMessages();
488         }
489     }
490 
logd(String str)491     private static void logd(String str) {
492         Log.d(TAG, str);
493     }
494 }
495