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 android.telephony.mockmodem; 18 19 import static android.telephony.mockmodem.MockSimService.MOCK_SIM_PROFILE_ID_DEFAULT; 20 21 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_RADIO_POWER; 22 23 import android.content.Context; 24 import android.hardware.radio.sim.Carrier; 25 import android.hardware.radio.sim.CarrierRestrictions; 26 import android.hardware.radio.voice.CdmaSignalInfoRecord; 27 import android.hardware.radio.voice.UusInfo; 28 import android.os.Build; 29 import android.os.Looper; 30 import android.os.SystemProperties; 31 import android.telephony.Annotation; 32 import android.telephony.BarringInfo; 33 import android.telephony.SubscriptionManager; 34 import android.telephony.TelephonyManager; 35 import android.telephony.cts.util.TelephonyUtils; 36 import android.telephony.ims.feature.ConnectionFailureInfo; 37 import android.telephony.ims.feature.MmTelFeature; 38 import android.telephony.ims.stub.ImsRegistrationImplBase; 39 import android.util.Log; 40 import android.util.SparseArray; 41 42 import androidx.test.InstrumentationRegistry; 43 44 import com.android.compatibility.common.util.TestThread; 45 46 import java.util.List; 47 import java.util.Set; 48 import java.util.concurrent.TimeUnit; 49 import java.util.function.BooleanSupplier; 50 51 public class MockModemManager { 52 private static final String TAG = "MockModemManager"; 53 private static final boolean DEBUG = !"user".equals(Build.TYPE); 54 55 private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem"; 56 private static final String BOOT_ALLOW_MOCK_MODEM_PROPERTY = "ro.boot.radio.allow_mock_modem"; 57 58 private static Context sContext; 59 private static MockModemServiceConnector sServiceConnector; 60 private static final long TIMEOUT_IN_MSEC_FOR_SIM_STATUS_CHANGED = 10000; 61 private static final int WAIT_UPDATE_TIMEOUT_MS = 200; // 0.2sec delay 62 private MockModemService mMockModemService; 63 enforceMockModemDeveloperSetting()64 public static void enforceMockModemDeveloperSetting() throws Exception { 65 boolean isAllowed = SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false); 66 boolean isAllowedForBoot = 67 SystemProperties.getBoolean(BOOT_ALLOW_MOCK_MODEM_PROPERTY, false); 68 // Check for developer settings for user build. Always allow for debug builds 69 if (!(isAllowed || isAllowedForBoot) && !DEBUG) { 70 throw new IllegalStateException( 71 "!! Enable Mock Modem before running this test !! " 72 + "Developer options => Allow Mock Modem"); 73 } 74 } 75 MockModemManager()76 public MockModemManager() { 77 sContext = InstrumentationRegistry.getInstrumentation().getContext(); 78 } 79 waitForTelephonyFrameworkDone(int delayInSec)80 private void waitForTelephonyFrameworkDone(int delayInSec) throws Exception { 81 TimeUnit.SECONDS.sleep(delayInSec); 82 } 83 waitForSubscriptionCondition(BooleanSupplier condition, long maxWaitMillis)84 private void waitForSubscriptionCondition(BooleanSupplier condition, long maxWaitMillis) 85 throws Exception { 86 final Object lock = new Object(); 87 SubscriptionManager sm = 88 (SubscriptionManager) 89 sContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); 90 91 TestThread t = 92 new TestThread( 93 () -> { 94 Looper.prepare(); 95 96 SubscriptionManager.OnSubscriptionsChangedListener listener = 97 new SubscriptionManager.OnSubscriptionsChangedListener() { 98 @Override 99 public void onSubscriptionsChanged() { 100 synchronized (lock) { 101 if (condition.getAsBoolean()) { 102 lock.notifyAll(); 103 Looper.myLooper().quitSafely(); 104 } 105 } 106 } 107 }; 108 109 sm.addOnSubscriptionsChangedListener(listener); 110 try { 111 synchronized (lock) { 112 if (condition.getAsBoolean()) lock.notifyAll(); 113 } 114 Log.d(TAG, "before loop()...."); 115 if (!condition.getAsBoolean()) Looper.loop(); 116 Log.d(TAG, "after loop()...."); 117 } finally { 118 sm.removeOnSubscriptionsChangedListener(listener); 119 } 120 }); 121 122 synchronized (lock) { 123 if (condition.getAsBoolean()) return; 124 t.start(); 125 lock.wait(maxWaitMillis); 126 } 127 } 128 129 /* Public APIs */ 130 131 /** 132 * Bring up Mock Modem Service and connect to it. 133 * 134 * @return boolean true if the operation is successful, otherwise false. 135 */ connectMockModemService()136 public boolean connectMockModemService() throws Exception { 137 return connectMockModemService(MOCK_SIM_PROFILE_ID_DEFAULT); 138 } 139 140 /** 141 * Bring up Mock Modem Service and connect to it. 142 * 143 * @pararm simprofile for initial Sim profile 144 * @return boolean true if the operation is successful, otherwise false. 145 */ connectMockModemService(int simprofile)146 public boolean connectMockModemService(int simprofile) throws Exception { 147 int[] simprofiles = new int[1]; 148 simprofiles[0] = Integer.valueOf(simprofile); 149 150 return connectMockModemService(simprofiles); 151 } 152 153 /** 154 * Bring up Mock Modem Service and connect to it. 155 * 156 * @param simprofiles for initial Sim profile of multiple Sim slots 157 * @return boolean true if the operation is successful, otherwise false. 158 */ connectMockModemService(int[] simprofiles)159 public boolean connectMockModemService(int[] simprofiles) throws Exception { 160 boolean result = true; 161 162 if (simprofiles == null) { 163 Log.e(TAG, "The parameter is invalid."); 164 result = false; 165 } 166 167 if (result && sServiceConnector == null) { 168 sServiceConnector = 169 new MockModemServiceConnector(InstrumentationRegistry.getInstrumentation()); 170 } 171 172 if (result && sServiceConnector != null) { 173 result = sServiceConnector.connectMockModemService(simprofiles); 174 175 if (result) { 176 mMockModemService = sServiceConnector.getMockModemService(); 177 178 if (mMockModemService != null) { 179 /* 180 It needs to have a delay to wait for Telephony Framework to bind with 181 MockModemService and set radio power as a desired state for initial condition 182 even get SIM card state. Currently, 1 sec is enough for now. 183 */ 184 waitForTelephonyFrameworkDone(1); 185 } else { 186 Log.e(TAG, "MockModemService get failed!"); 187 result = false; 188 } 189 } 190 } else { 191 Log.e(TAG, "Create MockModemServiceConnector failed!"); 192 } 193 194 return result; 195 } 196 197 /** 198 * Disconnect from Mock Modem Service. 199 * 200 * @return boolean true if the operation is successful, otherwise false. 201 */ disconnectMockModemService()202 public boolean disconnectMockModemService() throws Exception { 203 boolean result = false; 204 205 if (sServiceConnector != null) { 206 result = sServiceConnector.disconnectMockModemService(); 207 208 if (result) { 209 mMockModemService = null; 210 } else { 211 Log.e(TAG, "MockModemService disconnected failed!"); 212 } 213 } else { 214 Log.e(TAG, "No MockModemServiceConnector exist!"); 215 } 216 217 return result; 218 } 219 220 /** 221 * Query whether an active SIM card is present on this slot or not. 222 * 223 * @param slotId which slot would be checked. 224 * @return boolean true if any sim card inserted, otherwise false. 225 */ isSimCardPresent(int slotId)226 public boolean isSimCardPresent(int slotId) throws Exception { 227 Log.d(TAG, "isSimCardPresent[" + slotId + "]"); 228 229 MockModemConfigInterface configInterface = mMockModemService.getMockModemConfigInterface(); 230 return (configInterface != null) ? configInterface.isSimCardPresent(slotId, TAG) : false; 231 } 232 233 /** 234 * Insert a SIM card. 235 * 236 * @param slotId which slot would insert. 237 * @param simProfileId which carrier sim card is inserted. 238 * @return boolean true if the operation is successful, otherwise false. 239 */ insertSimCard(int slotId, int simProfileId)240 public boolean insertSimCard(int slotId, int simProfileId) throws Exception { 241 Log.d(TAG, "insertSimCard[" + slotId + "] with profile Id(" + simProfileId + ")"); 242 boolean result = true; 243 244 if (!isSimCardPresent(slotId)) { 245 MockModemConfigInterface configInterface = 246 mMockModemService.getMockModemConfigInterface(); 247 if (configInterface != null) { 248 TelephonyManager tm = sContext.getSystemService(TelephonyManager.class); 249 250 result = configInterface.changeSimProfile(slotId, simProfileId, TAG); 251 if (result) { 252 try { 253 waitForSubscriptionCondition( 254 () -> (TelephonyManager.SIM_STATE_PRESENT == tm.getSimCardState()), 255 TIMEOUT_IN_MSEC_FOR_SIM_STATUS_CHANGED); 256 } finally { 257 Log.d(TAG, "Insert Sim - subscription changed."); 258 } 259 } 260 } 261 } else { 262 Log.d(TAG, "There is a SIM inserted. Need to remove first."); 263 result = false; 264 } 265 return result; 266 } 267 268 /** 269 * Remove a SIM card. 270 * 271 * @param slotId which slot would remove the SIM. 272 * @return boolean true if the operation is successful, otherwise false. 273 */ removeSimCard(int slotId)274 public boolean removeSimCard(int slotId) throws Exception { 275 Log.d(TAG, "removeSimCard[" + slotId + "]"); 276 boolean result = true; 277 278 if (isSimCardPresent(slotId)) { 279 MockModemConfigInterface configInterface = 280 mMockModemService.getMockModemConfigInterface(); 281 if (configInterface != null) { 282 TelephonyManager tm = sContext.getSystemService(TelephonyManager.class); 283 284 result = configInterface.changeSimProfile(slotId, MOCK_SIM_PROFILE_ID_DEFAULT, TAG); 285 if (result) { 286 try { 287 waitForSubscriptionCondition( 288 () -> (TelephonyManager.SIM_STATE_ABSENT == tm.getSimCardState()), 289 TIMEOUT_IN_MSEC_FOR_SIM_STATUS_CHANGED); 290 } finally { 291 Log.d(TAG, "Remove Sim - subscription changed."); 292 } 293 } 294 } 295 } else { 296 Log.d(TAG, "There is no SIM inserted."); 297 result = false; 298 } 299 return result; 300 } 301 302 /** 303 * Modify SIM info of the SIM such as MCC/MNC, IMSI, etc. 304 * 305 * @param slotId for modifying. 306 * @param type the type of SIM info to modify. 307 * @param data to modify for the type of SIM info. 308 * @return boolean true if the operation is successful, otherwise false. 309 */ setSimInfo(int slotId, int type, String[] data)310 public boolean setSimInfo(int slotId, int type, String[] data) throws Exception { 311 Log.d(TAG, "setSimInfo[" + slotId + "]"); 312 boolean result = true; 313 314 if (isSimCardPresent(slotId)) { 315 MockModemConfigInterface configInterface = 316 mMockModemService.getMockModemConfigInterface(); 317 if (configInterface != null) { 318 configInterface.setSimInfo(slotId, type, data, TAG); 319 320 // Wait for telephony framework refresh data and carrier config 321 waitForTelephonyFrameworkDone(3); 322 } else { 323 Log.e(TAG, "MockModemConfigInterface == null!"); 324 result = false; 325 } 326 } else { 327 Log.d(TAG, "There is no SIM inserted."); 328 result = false; 329 } 330 return result; 331 } 332 333 /** 334 * Get SIM info of the SIM slot, e.g. MCC/MNC, IMSI. 335 * 336 * @param slotId for the query. 337 * @param type the type of SIM info. 338 * @return String the SIM info of the queried type. 339 */ getSimInfo(int slotId, int type)340 public String getSimInfo(int slotId, int type) throws Exception { 341 Log.d(TAG, "getSimInfo[" + slotId + "]"); 342 String result = ""; 343 344 if (isSimCardPresent(slotId)) { 345 MockModemConfigInterface configInterface = 346 mMockModemService.getMockModemConfigInterface(); 347 if (configInterface != null) { 348 result = configInterface.getSimInfo(slotId, type, TAG); 349 } 350 } else { 351 Log.d(TAG, "There is no SIM inserted."); 352 } 353 return result; 354 } 355 356 357 /** 358 * Sets the logical slots that are currently capable of performing cellular simultaneous 359 * calling. 360 * @param slotId The logical slot ID where the simultaneous calling state has changed 361 * @param enabledLogicalSlots The other logical slots that will have simultaneous calling 362 * enabled for this slot. 363 * @return true if the operation succeeded, false if it failed 364 */ setSimulCallingEnabledLogicalSlots(int slotId, int[] enabledLogicalSlots)365 public boolean setSimulCallingEnabledLogicalSlots(int slotId, 366 int[] enabledLogicalSlots) throws Exception { 367 Log.d(TAG, "setSimulCallingEnabledLogicalSlots[" + slotId + "]"); 368 boolean result = true; 369 370 if (isSimCardPresent(slotId)) { 371 MockModemConfigInterface configInterface = 372 mMockModemService.getMockModemConfigInterface(); 373 if (configInterface != null) { 374 configInterface.setSimulCallingEnabledLogicalSlots(slotId, enabledLogicalSlots, 375 TAG); 376 377 // Wait for telephony framework refresh data and carrier config 378 waitForTelephonyFrameworkDone(3); 379 } else { 380 Log.e(TAG, "setSimulCallingEnabledLogicalSlots: MockModemConfigInterface" 381 + " == null!"); 382 result = false; 383 } 384 } else { 385 Log.d(TAG, "setSimulCallingEnabledLogicalSlots: There is no SIM inserted."); 386 result = false; 387 } 388 return result; 389 } 390 391 /** 392 * Force the response error return for a specific RIL request 393 * 394 * @param slotId which slot needs to be set. 395 * @param requestId the request/response message ID 396 * @param error RIL_Errno and -1 means to disable the modified mechanism, back to original mock 397 * modem behavior 398 * @return boolean true if the operation is successful, otherwise false. 399 */ forceErrorResponse(int slotId, int requestId, int error)400 public boolean forceErrorResponse(int slotId, int requestId, int error) throws Exception { 401 Log.d( 402 TAG, 403 "forceErrorResponse[" + slotId + "] for request:" + requestId + " ,error:" + error); 404 boolean result = true; 405 406 switch (requestId) { 407 case RIL_REQUEST_RADIO_POWER: 408 mMockModemService 409 .getIRadioModem((byte) slotId) 410 .forceErrorResponse(requestId, error); 411 break; 412 default: 413 Log.e(TAG, "request:" + requestId + " not support to change the response error"); 414 result = false; 415 break; 416 } 417 return result; 418 } 419 420 /** 421 * Make the modem is in service or not. 422 * 423 * @param slotId which SIM slot is under the carrierId network. 424 * @param carrierId which carrier network is used. 425 * @param registration boolean true if the modem is in service, otherwise false. 426 * @return boolean true if the operation is successful, otherwise false. 427 */ changeNetworkService(int slotId, int carrierId, boolean registration)428 public boolean changeNetworkService(int slotId, int carrierId, boolean registration) 429 throws Exception { 430 Log.d( 431 TAG, 432 "changeNetworkService[" 433 + slotId 434 + "] in carrier (" 435 + carrierId 436 + ") " 437 + registration); 438 439 boolean result; 440 result = 441 mMockModemService 442 .getIRadioNetwork((byte) slotId) 443 .changeNetworkService(carrierId, registration); 444 445 waitForTelephonyFrameworkDone(1); 446 return result; 447 } 448 449 /** 450 * Make the modem is in service or not for CS or PS registration 451 * 452 * @param slotId which SIM slot is under the carrierId network. 453 * @param carrierId which carrier network is used. 454 * @param registration boolean true if the modem is in service, otherwise false. 455 * @param domainBitmask int specify domains (CS only, PS only, or both). 456 * @return boolean true if the operation is successful, otherwise false. 457 */ changeNetworkService( int slotId, int carrierId, boolean registration, int domainBitmask)458 public boolean changeNetworkService( 459 int slotId, int carrierId, 460 boolean registration, int domainBitmask) throws Exception { 461 return changeNetworkService( 462 slotId, carrierId, registration, domainBitmask, 0 /* regFailCause */); 463 } 464 465 /** 466 * Make the modem is in service or not for CS or PS registration 467 * 468 * @param slotId which SIM slot is under the carrierId network. 469 * @param carrierId which carrier network is used. 470 * @param registration boolean true if the modem is in service, otherwise false. 471 * @param domainBitmask int specify domains (CS only, PS only, or both). 472 * @param regFailCause int reason code for registration failure. 473 * @return boolean true if the operation is successful, otherwise false. 474 */ changeNetworkService( int slotId, int carrierId, boolean registration, int domainBitmask, int regFailCause)475 public boolean changeNetworkService( 476 int slotId, int carrierId, 477 boolean registration, int domainBitmask, 478 int regFailCause) throws Exception { 479 Log.d( 480 TAG, 481 "changeNetworkService[" 482 + slotId 483 + "] in carrier (" 484 + carrierId 485 + ") " 486 + registration 487 + " with domainBitmask = " 488 + domainBitmask 489 + " with failCause = " 490 + regFailCause); 491 492 boolean result; 493 result = 494 mMockModemService 495 .getIRadioNetwork((byte) slotId) 496 .changeNetworkService( 497 carrierId, registration, domainBitmask, regFailCause); 498 499 waitForTelephonyFrameworkDone(1); 500 return result; 501 } 502 503 /** 504 * get GSM CellBroadcastConfig outputs from IRadioMessagingImpl 505 * 506 * @param slotId which slot would insert 507 * @return Set of broadcast configs 508 */ getGsmBroadcastConfig(int slotId)509 public Set<Integer> getGsmBroadcastConfig(int slotId) { 510 return mMockModemService.getIRadioMessaging((byte) slotId).getGsmBroadcastConfigSet(); 511 } 512 513 /** 514 * get CDMA CellBroadcastConfig outputs from IRadioMessagingImpl 515 * 516 * @param slotId which slot would insert 517 * @return Set of broadcast configs 518 */ getCdmaBroadcastConfig(int slotId)519 public Set<Integer> getCdmaBroadcastConfig(int slotId) { 520 return mMockModemService.getIRadioMessaging((byte) slotId).getCdmaBroadcastConfigSet(); 521 } 522 523 /** 524 * receive new broadcast sms message 525 * 526 * @param slotId which slot would insert 527 * @param data data of broadcast messages to be received 528 */ newBroadcastSms(int slotId, byte[] data)529 public void newBroadcastSms(int slotId, byte[] data) { 530 mMockModemService.getIRadioMessaging((byte) slotId).newBroadcastSms(data); 531 } 532 533 /** 534 * register callback for monitoring broadcast activation 535 * 536 * @param slotId which slot would insert 537 * @param callback callback to register 538 */ registerBroadcastCallback(int slotId, IRadioMessagingImpl.CallBackWithExecutor callback)539 public void registerBroadcastCallback(int slotId, 540 IRadioMessagingImpl.CallBackWithExecutor callback) { 541 mMockModemService.getIRadioMessaging((byte) slotId).registerBroadcastCallback(callback); 542 } 543 544 /** 545 * unregister callback for monitoring broadcast activation 546 * 547 * @param slotId which slot would insert 548 * @param callback callback to unregister 549 */ unregisterBroadcastCallback(int slotId, IRadioMessagingImpl.CallBackWithExecutor callback)550 public void unregisterBroadcastCallback(int slotId, 551 IRadioMessagingImpl.CallBackWithExecutor callback) { 552 mMockModemService.getIRadioMessaging((byte) slotId).unregisterBroadcastCallback(callback); 553 } 554 555 /** 556 * Indicates when Single Radio Voice Call Continuity (SRVCC) progress state has changed. 557 * 558 * @param slotId which slot would insert. 559 * @param state New SRVCC State 560 * @return boolean true if the operation is successful, otherwise false. 561 */ srvccStateNotify(int slotId, int state)562 public boolean srvccStateNotify(int slotId, int state) { 563 Log.d(TAG, "notifySrvccState[" + slotId + "] with state(" + state + ")"); 564 565 boolean result = false; 566 try { 567 IRadioVoiceImpl radioVoice = mMockModemService.getIRadioVoice((byte) slotId); 568 if (radioVoice != null) { 569 radioVoice.srvccStateNotify(state); 570 571 waitForTelephonyFrameworkDone(1); 572 result = true; 573 } 574 } catch (Exception e) { 575 } 576 return result; 577 } 578 579 /** 580 * Returns the list of MockSrvccCall 581 * 582 * @param slotId for which slot to get the list 583 * @return the list of {@link MockSrvccCall} 584 */ getSrvccCalls(int slotId)585 public List<MockSrvccCall> getSrvccCalls(int slotId) { 586 Log.d(TAG, "getSrvccCalls[" + slotId + "]"); 587 588 IRadioImsImpl radioIms = mMockModemService.getIRadioIms((byte) slotId); 589 if (radioIms == null) return null; 590 return radioIms.getSrvccCalls(); 591 } 592 593 /** 594 * Triggers IMS deregistration. 595 * 596 * @param slotId which slot would insert. 597 * @param reason the reason why the deregistration is triggered. 598 * @return {@code true} if the operation is successful, otherwise {@code false}. 599 */ triggerImsDeregistration(int slotId, @ImsRegistrationImplBase.ImsDeregistrationReason int reason)600 public boolean triggerImsDeregistration(int slotId, 601 @ImsRegistrationImplBase.ImsDeregistrationReason int reason) { 602 Log.d(TAG, "triggerImsDeregistration[" + slotId + "] reason=" + reason); 603 604 boolean result = false; 605 try { 606 mMockModemService.getIRadioIms().triggerImsDeregistration(reason); 607 608 waitForTelephonyFrameworkDone(1); 609 result = true; 610 } catch (Exception e) { 611 } 612 return result; 613 } 614 615 /** 616 * Clears the Anbr values. 617 * 618 * @param slotId for which slot to get the reason. 619 */ resetAnbrValues(int slotId)620 public void resetAnbrValues(int slotId) { 621 Log.d(TAG, "resetAnbrValues[" + slotId + "]"); 622 623 try { 624 IRadioImsImpl radioIms = mMockModemService.getIRadioIms((byte) slotId); 625 if (radioIms == null) return; 626 radioIms.resetAnbrValues(); 627 } catch (Exception e) { 628 Log.e(TAG, "resetAnbrValues - failed"); 629 } 630 } 631 632 /** 633 * Returns the Anbr values. 634 * 635 * @param slotId for which slot to get the reason. 636 * @return the Anbr values triggered by Anbr Query. 637 */ getAnbrValues(int slotId)638 public int[] getAnbrValues(int slotId) { 639 Log.d(TAG, "getAnbrValues[" + slotId + "]"); 640 641 IRadioImsImpl radioIms = mMockModemService.getIRadioIms((byte) slotId); 642 if (radioIms == null) return null; 643 return radioIms.getAnbrValues(); 644 } 645 646 /** 647 * Triggers NotifyAnbr. 648 * 649 * @param slotId which slot would insert. 650 * @param qosSessionId is used to identify media stream such as audio or video. 651 * @param direction Direction of this packet stream (e.g. uplink or downlink). 652 * @param bitsPerSecond is the bitrate received from the NW through the Recommended 653 * bitrate MAC Control Element message and ImsStack converts this value from MAC bitrate 654 * to audio/video codec bitrate (defined in TS26.114). 655 * @return {@code true} if the operation is successful, otherwise {@code false}. 656 */ notifyAnbr(int slotId, int qosSessionId, int direction, int bitsPerSecond)657 public boolean notifyAnbr(int slotId, int qosSessionId, int direction, int bitsPerSecond) { 658 Log.d(TAG, "mockmodem - notifyAnbr[" + slotId + "] qosSessionId=" + qosSessionId 659 + ", direction=" + direction + ", bitsPerSecond" + bitsPerSecond); 660 661 boolean result = false; 662 try { 663 664 IRadioImsImpl radioIms = mMockModemService.getIRadioIms((byte) slotId); 665 if (radioIms == null) return false; 666 radioIms.notifyAnbr(qosSessionId, direction, bitsPerSecond); 667 668 waitForTelephonyFrameworkDone(1); 669 result = true; 670 } catch (Exception e) { 671 Log.e(TAG, "Create notifyAnbr - failed"); 672 } 673 return result; 674 } 675 676 /** 677 * Returns the reason that caused EPS fallback. 678 * 679 * @param slotId for which slot to get the reason 680 * @return the reason that caused EPS fallback. 681 */ getEpsFallbackReason(int slotId)682 public @MmTelFeature.EpsFallbackReason int getEpsFallbackReason(int slotId) { 683 Log.d(TAG, "getEpsFallbackReason[" + slotId + "]"); 684 685 IRadioImsImpl radioIms = mMockModemService.getIRadioIms((byte) slotId); 686 if (radioIms == null) return -1; 687 return radioIms.getEpsFallbackReason(); 688 } 689 690 /** 691 * Clears the EPS fallback reason. 692 * 693 * @param slotId for which slot to get the reason 694 */ resetEpsFallbackReason(int slotId)695 public void resetEpsFallbackReason(int slotId) { 696 Log.d(TAG, "resetEpsFallbackReason[" + slotId + "]"); 697 698 IRadioImsImpl radioIms = mMockModemService.getIRadioIms((byte) slotId); 699 if (radioIms == null) return; 700 radioIms.resetEpsFallbackReason(); 701 } 702 703 /** 704 * Updates the emergency registration state. 705 * 706 * @param slotId the Id of logical sim slot. 707 * @param regResult the emergency registration state. 708 */ setEmergencyRegResult(int slotId, MockEmergencyRegResult regResult)709 public void setEmergencyRegResult(int slotId, MockEmergencyRegResult regResult) { 710 Log.d(TAG, "setEmergencyRegResult[" + slotId + "]"); 711 mMockModemService.getIRadioNetwork((byte) slotId).setEmergencyRegResult(regResult); 712 } 713 714 /** 715 * Notifies the barring information change. 716 * 717 * @param slotId the Id of logical sim slot. 718 * @param barringServiceInfos the barring information. 719 */ unsolBarringInfoChanged(int slotId, SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos)720 public boolean unsolBarringInfoChanged(int slotId, 721 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos) { 722 Log.d(TAG, "unsolBarringInfoChanged[" + slotId + "]"); 723 return mMockModemService.getIRadioNetwork((byte) slotId) 724 .unsolBarringInfoChanged(barringServiceInfos); 725 } 726 727 /** 728 * Triggers RIL_UNSOL_EMERGENCY_NETWORK_SCAN_RESULT unsol message. 729 * 730 * @param slotId the Id of logical sim slot. 731 * @param regResult the registration result. 732 */ unsolEmergencyNetworkScanResult(int slotId, MockEmergencyRegResult regResult)733 public boolean unsolEmergencyNetworkScanResult(int slotId, MockEmergencyRegResult regResult) { 734 Log.d(TAG, "unsolEmergencyNetworkScanResult[" + slotId + "]"); 735 return mMockModemService.getIRadioNetwork((byte) slotId) 736 .unsolEmergencyNetworkScanResult(regResult); 737 } 738 739 /** 740 * Resets the current emergency mode. 741 * 742 * @param slotId the Id of logical sim slot. 743 */ resetEmergencyMode(int slotId)744 public void resetEmergencyMode(int slotId) { 745 Log.d(TAG, "resetEmergencyMode[" + slotId + "]"); 746 mMockModemService.getIRadioNetwork((byte) slotId).resetEmergencyMode(); 747 } 748 749 /** 750 * @return the current emergency mode. 751 * 752 * @param slotId the Id of logical sim slot. 753 */ getEmergencyMode(int slotId)754 public int getEmergencyMode(int slotId) { 755 Log.d(TAG, "getEmergencyMode[" + slotId + "]"); 756 return mMockModemService.getIRadioNetwork((byte) slotId).getEmergencyMode(); 757 } 758 759 /** 760 * Returns whether emergency network scan is triggered. 761 * 762 * @param slotId the Id of logical sim slot. 763 * @return {@code true} if emergency network scan is triggered. 764 */ isEmergencyNetworkScanTriggered(int slotId)765 public boolean isEmergencyNetworkScanTriggered(int slotId) { 766 Log.d(TAG, "isEmergencyNetworkScanTriggered[" + slotId + "]"); 767 return mMockModemService.getIRadioNetwork((byte) slotId).isEmergencyNetworkScanTriggered(); 768 } 769 770 /** 771 * Returns whether emergency network scan is canceled. 772 * 773 * @param slotId the Id of logical sim slot. 774 * @return {@code true} if emergency network scan is canceled. 775 */ isEmergencyNetworkScanCanceled(int slotId)776 public boolean isEmergencyNetworkScanCanceled(int slotId) { 777 Log.d(TAG, "isEmergencyNetworkScanCanceled[" + slotId + "]"); 778 return mMockModemService.getIRadioNetwork((byte) slotId).isEmergencyNetworkScanCanceled(); 779 } 780 781 /** 782 * Returns the list of preferred network type. 783 * 784 * @param slotId the Id of logical sim slot. 785 * @return the list of preferred network type. 786 */ getEmergencyNetworkScanAccessNetwork(int slotId)787 public int[] getEmergencyNetworkScanAccessNetwork(int slotId) { 788 Log.d(TAG, "getEmergencyNetworkScanAccessNetwork[" + slotId + "]"); 789 return mMockModemService.getIRadioNetwork((byte) slotId) 790 .getEmergencyNetworkScanAccessNetwork(); 791 } 792 793 /** 794 * Returns the preferred scan type. 795 * 796 * @param slotId the Id of logical sim slot. 797 * @return the preferred scan type. 798 */ getEmergencyNetworkScanType(int slotId)799 public int getEmergencyNetworkScanType(int slotId) { 800 Log.d(TAG, "getEmergencyNetworkScanType[" + slotId + "]"); 801 return mMockModemService.getIRadioNetwork((byte) slotId).getEmergencyNetworkScanType(); 802 } 803 804 /** 805 * Resets the emergency network scan attributes. 806 * 807 * @param slotId the Id of logical sim slot. 808 */ resetEmergencyNetworkScan(int slotId)809 public void resetEmergencyNetworkScan(int slotId) { 810 Log.d(TAG, "resetEmergencyNetworkScan[" + slotId + "]"); 811 mMockModemService.getIRadioNetwork((byte) slotId).resetEmergencyNetworkScan(); 812 } 813 814 /** 815 * Waits for the event of network service. 816 * 817 * @param slotId the Id of logical sim slot. 818 * @param latchIndex The index of the event. 819 * @param waitMs The timeout in milliseconds. 820 */ waitForNetworkLatchCountdown(int slotId, int latchIndex, int waitMs)821 public boolean waitForNetworkLatchCountdown(int slotId, int latchIndex, int waitMs) { 822 Log.d(TAG, "waitForNetworkLatchCountdown[" + slotId + "]"); 823 return mMockModemService.getIRadioNetwork((byte) slotId) 824 .waitForLatchCountdown(latchIndex, waitMs); 825 } 826 827 /** 828 * Resets the CountDownLatches of network service. 829 * 830 * @param slotId the Id of logical sim slot. 831 */ resetNetworkAllLatchCountdown(int slotId)832 public void resetNetworkAllLatchCountdown(int slotId) { 833 Log.d(TAG, "resetNetworkAllLatchCountdown[" + slotId + "]"); 834 mMockModemService.getIRadioNetwork((byte) slotId).resetAllLatchCountdown(); 835 } 836 837 /** 838 * Waits for the event of voice service. 839 * 840 * @param slotId the Id of logical sim slot. 841 * @param latchIndex The index of the event. 842 * @param waitMs The timeout in milliseconds. 843 */ waitForVoiceLatchCountdown(int slotId, int latchIndex, int waitMs)844 public boolean waitForVoiceLatchCountdown(int slotId, int latchIndex, int waitMs) { 845 Log.d(TAG, "waitForVoiceLatchCountdown[" + slotId + "]"); 846 return mMockModemService.getIRadioVoice((byte) slotId) 847 .waitForLatchCountdown(latchIndex, waitMs); 848 } 849 850 /** 851 * Resets the CountDownLatches of voice service. 852 * 853 * @param slotId the Id of logical sim slot. 854 */ resetVoiceAllLatchCountdown(int slotId)855 public void resetVoiceAllLatchCountdown(int slotId) { 856 Log.d(TAG, "resetVoiceAllLatchCountdown[" + slotId + "]"); 857 mMockModemService.getIRadioVoice((byte) slotId).resetAllLatchCountdown(); 858 } 859 860 /** 861 * Stops sending default response to startImsTraffic. 862 * 863 * @param slotId which slot would insert. 864 * @param blocked indicates whether sending response is allowed or not. 865 */ blockStartImsTrafficResponse(int slotId, boolean blocked)866 public void blockStartImsTrafficResponse(int slotId, boolean blocked) { 867 Log.d(TAG, "blockStartImsTrafficResponse[" + slotId + "] blocked(" + blocked + ")"); 868 869 mMockModemService.getIRadioIms((byte) slotId).blockStartImsTrafficResponse(blocked); 870 } 871 872 /** 873 * Returns whether the given IMS traffic type is started or not. 874 * 875 * @param slotId which slot would insert. 876 * @param trafficType the IMS traffic type 877 * @return boolean true if the given IMS traffic type is started 878 */ isImsTrafficStarted(int slotId, @MmTelFeature.ImsTrafficType int trafficType)879 public boolean isImsTrafficStarted(int slotId, 880 @MmTelFeature.ImsTrafficType int trafficType) { 881 Log.d(TAG, "isImsTrafficStarted[" + slotId + "] trafficType(" + trafficType + ")"); 882 883 return mMockModemService.getIRadioIms((byte) slotId).isImsTrafficStarted(trafficType); 884 } 885 886 /** 887 * Sends the response with the given information. 888 * 889 * @param slotId which slot would insert. 890 * @param trafficType the IMS traffic type 891 * @param reason The reason of failure. 892 * @param causeCode Failure cause code from network or modem specific to the failure. 893 * @param waitTimeMillis Retry wait time provided by network in milliseconds. 894 * @return boolean true if there is no error 895 */ sendStartImsTrafficResponse(int slotId, @MmTelFeature.ImsTrafficType int trafficType, @ConnectionFailureInfo.FailureReason int reason, int causeCode, int waitTimeMillis)896 public boolean sendStartImsTrafficResponse(int slotId, 897 @MmTelFeature.ImsTrafficType int trafficType, 898 @ConnectionFailureInfo.FailureReason int reason, 899 int causeCode, int waitTimeMillis) { 900 Log.d(TAG, "sendStartImsTrafficResponse[" + slotId 901 + "] trafficType(" + trafficType + ")" 902 + " reason(" + reason + ")" 903 + " cause(" + causeCode + ")" 904 + " wait(" + waitTimeMillis + ")"); 905 906 boolean result = false; 907 try { 908 mMockModemService.getIRadioIms((byte) slotId).sendStartImsTrafficResponse( 909 trafficType, reason, causeCode, waitTimeMillis); 910 911 waitForTelephonyFrameworkDone(1); 912 result = true; 913 } catch (Exception e) { 914 Log.e(TAG, "sendStartImsTrafficResponse e=" + e); 915 } 916 return result; 917 } 918 919 /** 920 * Notifies the connection failure info 921 * 922 * @param slotId which slot would insert. 923 * @param trafficType the IMS traffic type 924 * @param reason The reason of failure. 925 * @param causeCode Failure cause code from network or modem specific to the failure. 926 * @param waitTimeMillis Retry wait time provided by network in milliseconds. 927 * @return boolean true if there is no error 928 */ sendConnectionFailureInfo(int slotId, @MmTelFeature.ImsTrafficType int trafficType, @ConnectionFailureInfo.FailureReason int reason, int causeCode, int waitTimeMillis)929 public boolean sendConnectionFailureInfo(int slotId, 930 @MmTelFeature.ImsTrafficType int trafficType, 931 @ConnectionFailureInfo.FailureReason int reason, 932 int causeCode, int waitTimeMillis) { 933 Log.d(TAG, "sendConnectionFailureInfo[" + slotId 934 + "] trafficType(" + trafficType + ")" 935 + " reason(" + reason + ")" 936 + " cause(" + causeCode + ")" 937 + " wait(" + waitTimeMillis + ")"); 938 939 boolean result = false; 940 try { 941 mMockModemService.getIRadioIms((byte) slotId).sendConnectionFailureInfo( 942 trafficType, reason, causeCode, waitTimeMillis); 943 944 waitForTelephonyFrameworkDone(1); 945 result = true; 946 } catch (Exception e) { 947 Log.e(TAG, "sendConnectionFailureInfo e=" + e); 948 } 949 return result; 950 } 951 952 /** 953 * Clears the IMS traffic state. 954 */ clearImsTrafficState()955 public void clearImsTrafficState() { 956 mMockModemService.getIRadioIms().clearImsTrafficState(); 957 } 958 959 /** 960 * Waits for the event of mock IMS state. 961 * 962 * @param latchIndex The index of the event. 963 * @param waitMs The timeout in milliseconds. 964 */ waitForImsLatchCountdown(int latchIndex, int waitMs)965 public boolean waitForImsLatchCountdown(int latchIndex, int waitMs) { 966 return mMockModemService.getIRadioIms().waitForLatchCountdown(latchIndex, waitMs); 967 } 968 969 /** Resets the CountDownLatches of IMS state. */ resetImsAllLatchCountdown()970 public void resetImsAllLatchCountdown() { 971 mMockModemService.getIRadioIms().resetAllLatchCountdown(); 972 } 973 974 /** 975 * Set/override default call control configuration. 976 * 977 * @param slotId the Id of logical sim slot. 978 * @param callControlInfo the configuration of call control would like to override. 979 * @return boolean true if the operation succeeds, otherwise false. 980 */ setCallControlInfo(int slotId, MockCallControlInfo callControlInfo)981 public boolean setCallControlInfo(int slotId, MockCallControlInfo callControlInfo) { 982 Log.d(TAG, "setCallControlInfo[" + slotId + "]"); 983 return mMockModemService 984 .getMockModemConfigInterface() 985 .setCallControlInfo(slotId, callControlInfo, TAG); 986 } 987 988 /** 989 * Get call control configuration. 990 * 991 * @param slotId the Id of logical sim slot. 992 * @return MockCallControlInfo which was set/overridden before. 993 */ getCallControlInfo(int slotId)994 public MockCallControlInfo getCallControlInfo(int slotId) { 995 Log.d(TAG, "getCallControlInfo[" + slotId + "]"); 996 return mMockModemService.getMockModemConfigInterface().getCallControlInfo(slotId, TAG); 997 } 998 999 /** 1000 * Trigger an incoming voice call. 1001 * 1002 * @param slotId the Id of logical sim slot. 1003 * @param address phone number of the incoming call 1004 * @param uusInfo user to user signaling information. 1005 * @param cdmaSignalInfoRecord CDMA Signal Information Record. 1006 * @return boolean true if the operation succeeds, otherwise false. 1007 */ triggerIncomingVoiceCall( int slotId, String address, UusInfo[] uusInfo, CdmaSignalInfoRecord cdmaSignalInfoRecord)1008 public boolean triggerIncomingVoiceCall( 1009 int slotId, 1010 String address, 1011 UusInfo[] uusInfo, 1012 CdmaSignalInfoRecord cdmaSignalInfoRecord) 1013 throws Exception { 1014 return triggerIncomingVoiceCall(slotId, address, uusInfo, cdmaSignalInfoRecord, null); 1015 } 1016 1017 /** 1018 * Trigger an incoming voice call with a call control configuration. 1019 * 1020 * @param slotId the Id of logical sim slot. 1021 * @param address phone number of the incoming call 1022 * @param uusInfo user to user signaling information. 1023 * @param cdmaSignalInfoRecord CDMA Signal Information Record. 1024 * @param callControlInfo the configuration of call control would like to override. 1025 * @return boolean true if the operation succeeds, otherwise false. 1026 */ triggerIncomingVoiceCall( int slotId, String address, UusInfo[] uusInfo, CdmaSignalInfoRecord cdmaSignalInfoRecord, MockCallControlInfo callControlInfo)1027 public boolean triggerIncomingVoiceCall( 1028 int slotId, 1029 String address, 1030 UusInfo[] uusInfo, 1031 CdmaSignalInfoRecord cdmaSignalInfoRecord, 1032 MockCallControlInfo callControlInfo) 1033 throws Exception { 1034 Log.d(TAG, "triggerIncomingVoiceCall[" + slotId + "] address: " + address); 1035 boolean result; 1036 1037 result = 1038 mMockModemService 1039 .getMockModemConfigInterface() 1040 .triggerIncomingVoiceCall( 1041 slotId, 1042 address, 1043 uusInfo, 1044 cdmaSignalInfoRecord, 1045 callControlInfo, 1046 TAG); 1047 1048 waitForTelephonyFrameworkDone(1); 1049 return result; 1050 } 1051 1052 /** 1053 * Get number of on going CS calls. 1054 * 1055 * @param slotId the Id of logical sim slot. 1056 * @return int the number of CS calls. 1057 */ getNumberOfOngoingCSCalls(int slotId)1058 public int getNumberOfOngoingCSCalls(int slotId) { 1059 Log.d(TAG, "getNumberOfOngoingCSCalls[" + slotId + "]"); 1060 return mMockModemService.getMockModemConfigInterface().getNumberOfCalls(slotId, TAG); 1061 } 1062 1063 /** 1064 * Sets the last call fail cause. 1065 * 1066 * @param slotId the Id of logical sim slot. 1067 * @param cause The disconnect cause. 1068 */ setLastCallFailCause(int slotId, int cause)1069 public void setLastCallFailCause(int slotId, int cause) { 1070 Log.d(TAG, "setLastCallFailCause[" + slotId + "] cause = " + cause); 1071 mMockModemService.getMockModemConfigInterface().setLastCallFailCause(slotId, cause, TAG); 1072 } 1073 1074 /** 1075 * Clears all calls with the given cause. 1076 * 1077 * @param slotId the Id of logical sim slot. 1078 * @param cause The disconnect cause. 1079 */ clearAllCalls(int slotId, @Annotation.DisconnectCauses int cause)1080 public void clearAllCalls(int slotId, @Annotation.DisconnectCauses int cause) { 1081 Log.d(TAG, "clearAllCalls[" + slotId + "] cause = " + cause); 1082 mMockModemService.getMockModemConfigInterface().clearAllCalls(slotId, cause, TAG); 1083 } 1084 1085 /** 1086 * Reports the list of emergency numbers. 1087 * 1088 * @param numbers The list of emergency numbers. 1089 */ notifyEmergencyNumberList(int slotId, String[] numbers)1090 public void notifyEmergencyNumberList(int slotId, String[] numbers) { 1091 Log.d(TAG, "notifyEmergencyNumberList[" + slotId + "]"); 1092 mMockModemService.getIRadioVoice((byte) slotId).notifyEmergencyNumberList(numbers); 1093 } 1094 1095 /** 1096 * Sets the new carrierId and CarrierRestriction status values in IRadioSimImpl.java 1097 * @param carrierList 1098 * @param carrierRestrictionStatus 1099 */ updateCarrierRestrictionInfo(Carrier[] carrierList, int carrierRestrictionStatus)1100 public void updateCarrierRestrictionInfo(Carrier[] carrierList, int carrierRestrictionStatus) { 1101 mMockModemService.getIRadioSim().updateCarrierRestrictionStatusInfo(carrierList, 1102 carrierRestrictionStatus); 1103 } 1104 1105 /** 1106 * Helper method that can be called from the test suite to change the primary IMEi mapping 1107 * with respect to sim slot. 1108 */ changeImeiMapping()1109 public boolean changeImeiMapping() { 1110 int modemCount = mMockModemService.getActiveMockModemCount(); 1111 if (modemCount == 1) { 1112 return false; 1113 } 1114 for (int slotId = 0; slotId < modemCount; slotId++) { 1115 mMockModemService.getIRadioModem((byte) slotId).resetAllLatchCountdown(); 1116 mMockModemService.getIRadioModem((byte) slotId).changeImeiMapping(); 1117 if (waitForModemLatchCountdown(slotId, WAIT_UPDATE_TIMEOUT_MS)) { 1118 Log.e(TAG, "Error in waitForModemLatchCountdown"); 1119 } 1120 } 1121 return true; 1122 } 1123 1124 /** 1125 * Wait latch for 0.2 sec or latch to countdown. 1126 * @param slotId : slotId of the device. 1127 * @param waitMs : Wait in milliseconds for the latch-wait timeout. 1128 * @return true if latch is success else fail. 1129 */ waitForModemLatchCountdown(int slotId, int waitMs)1130 public boolean waitForModemLatchCountdown(int slotId, int waitMs) { 1131 Log.d(TAG, "waitForVoiceLatchCountdown[" + slotId + "]"); 1132 return mMockModemService.getIRadioModem((byte) slotId) 1133 .waitForLatchCountdown(slotId, waitMs); 1134 } 1135 setCarrierRestrictionRules(CarrierRestrictions carrierRestrictionRules, int multiSimPolicy)1136 public void setCarrierRestrictionRules(CarrierRestrictions carrierRestrictionRules, 1137 int multiSimPolicy) { 1138 mMockModemService.getIRadioSim().updateCarrierRestrictionRules( 1139 carrierRestrictionRules, multiSimPolicy); 1140 } 1141 1142 /** 1143 * Triggers an incoming SMS. 1144 * 1145 * @param slotId the Id of logical sim slot. 1146 * @return {@code true} if the operation succeeds otherwise false. 1147 */ triggerIncomingSms(int slotId)1148 public boolean triggerIncomingSms(int slotId) { 1149 Log.d(TAG, "triggerIncomingSms[" + slotId + "]"); 1150 1151 boolean result = false; 1152 try { 1153 String pdu = "07916164260220F0040B914151245584F600006060605130308A04D4F29C0E"; 1154 mMockModemService.getIRadioMessaging((byte) slotId) 1155 .newSms(TelephonyUtils.hexStringToByteArray(pdu)); 1156 1157 waitForTelephonyFrameworkDone(1); 1158 result = true; 1159 } catch (Exception e) { 1160 Log.e(TAG, "triggerIncomingSms e=" + e); 1161 } 1162 return result; 1163 } 1164 } 1165