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