1/* 2 * Copyright (C) 2006 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 17package com.android.internal.telephony.test; 18 19import android.os.AsyncResult; 20import android.os.Handler; 21import android.os.HandlerThread; 22import android.os.Looper; 23import android.os.Message; 24import android.os.Parcel; 25import android.os.Registrant; 26import android.os.SystemClock; 27import android.service.carrier.CarrierIdentifier; 28import android.telephony.CellInfo; 29import android.telephony.CellInfoGsm; 30import android.telephony.Rlog; 31import android.telephony.ServiceState; 32import android.telephony.SignalStrength; 33import android.telephony.IccOpenLogicalChannelResponse; 34 35import com.android.internal.annotations.VisibleForTesting; 36import com.android.internal.telephony.BaseCommands; 37import com.android.internal.telephony.CommandException; 38import com.android.internal.telephony.CommandsInterface; 39import com.android.internal.telephony.PhoneConstants; 40import com.android.internal.telephony.SmsResponse; 41import com.android.internal.telephony.RadioCapability; 42import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo; 43import com.android.internal.telephony.dataconnection.DataCallResponse; 44import com.android.internal.telephony.dataconnection.DataProfile; 45import com.android.internal.telephony.Phone; 46import com.android.internal.telephony.UUSInfo; 47import com.android.internal.telephony.CallFailCause; 48import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; 49import com.android.internal.telephony.gsm.SuppServiceNotification; 50import com.android.internal.telephony.LastCallFailCause; 51import com.android.internal.telephony.uicc.IccCardStatus; 52import com.android.internal.telephony.uicc.IccIoResult; 53 54import java.util.ArrayList; 55import java.util.concurrent.atomic.AtomicBoolean; 56import java.util.List; 57import java.util.concurrent.atomic.AtomicInteger; 58 59public class SimulatedCommands extends BaseCommands 60 implements CommandsInterface, SimulatedRadioControl { 61 private final static String LOG_TAG = "SimulatedCommands"; 62 63 private enum SimLockState { 64 NONE, 65 REQUIRE_PIN, 66 REQUIRE_PUK, 67 SIM_PERM_LOCKED 68 } 69 70 private enum SimFdnState { 71 NONE, 72 REQUIRE_PIN2, 73 REQUIRE_PUK2, 74 SIM_PERM_LOCKED 75 } 76 77 private final static SimLockState INITIAL_LOCK_STATE = SimLockState.NONE; 78 public final static String DEFAULT_SIM_PIN_CODE = "1234"; 79 private final static String SIM_PUK_CODE = "12345678"; 80 private final static SimFdnState INITIAL_FDN_STATE = SimFdnState.NONE; 81 public final static String DEFAULT_SIM_PIN2_CODE = "5678"; 82 private final static String SIM_PUK2_CODE = "87654321"; 83 public final static String FAKE_LONG_NAME = "Fake long name"; 84 public final static String FAKE_SHORT_NAME = "Fake short name"; 85 public final static String FAKE_MCC_MNC = "310260"; 86 public final static String FAKE_IMEI = "012345678901234"; 87 public final static String FAKE_IMEISV = "99"; 88 public final static String FAKE_ESN = "1234"; 89 public final static String FAKE_MEID = "1234"; 90 public final static int DEFAULT_PIN1_ATTEMPT = 5; 91 public final static int DEFAULT_PIN2_ATTEMPT = 5; 92 93 private String mImei; 94 private String mImeiSv; 95 96 //***** Instance Variables 97 98 SimulatedGsmCallState simulatedCallState; 99 HandlerThread mHandlerThread; 100 SimLockState mSimLockedState; 101 boolean mSimLockEnabled; 102 int mPinUnlockAttempts; 103 int mPukUnlockAttempts; 104 String mPinCode; 105 int mPin1attemptsRemaining = DEFAULT_PIN1_ATTEMPT; 106 SimFdnState mSimFdnEnabledState; 107 boolean mSimFdnEnabled; 108 int mPin2UnlockAttempts; 109 int mPuk2UnlockAttempts; 110 int mNetworkType; 111 String mPin2Code; 112 boolean mSsnNotifyOn = false; 113 private int mVoiceRegState = ServiceState.RIL_REG_STATE_HOME; 114 private int mVoiceRadioTech = ServiceState.RIL_RADIO_TECHNOLOGY_UMTS; 115 private int mDataRegState = ServiceState.RIL_REG_STATE_HOME; 116 private int mDataRadioTech = ServiceState.RIL_RADIO_TECHNOLOGY_UMTS; 117 private SignalStrength mSignalStrength; 118 private List<CellInfo> mCellInfoList; 119 private int[] mImsRegState; 120 private IccCardStatus mIccCardStatus; 121 private IccIoResult mIccIoResultForApduLogicalChannel; 122 private int mChannelId = IccOpenLogicalChannelResponse.INVALID_CHANNEL; 123 124 int mPausedResponseCount; 125 ArrayList<Message> mPausedResponses = new ArrayList<Message>(); 126 127 int mNextCallFailCause = CallFailCause.NORMAL_CLEARING; 128 129 private boolean mDcSuccess = true; 130 private DataCallResponse mDcResponse; 131 132 //***** Constructor 133 public 134 SimulatedCommands() { 135 super(null); // Don't log statistics 136 mHandlerThread = new HandlerThread("SimulatedCommands"); 137 mHandlerThread.start(); 138 Looper looper = mHandlerThread.getLooper(); 139 140 simulatedCallState = new SimulatedGsmCallState(looper); 141 142 setRadioState(RadioState.RADIO_ON); 143 mSimLockedState = INITIAL_LOCK_STATE; 144 mSimLockEnabled = (mSimLockedState != SimLockState.NONE); 145 mPinCode = DEFAULT_SIM_PIN_CODE; 146 mSimFdnEnabledState = INITIAL_FDN_STATE; 147 mSimFdnEnabled = (mSimFdnEnabledState != SimFdnState.NONE); 148 mPin2Code = DEFAULT_SIM_PIN2_CODE; 149 } 150 151 private void log(String str) { 152 Rlog.d(LOG_TAG, str); 153 } 154 155 //***** CommandsInterface implementation 156 157 @Override 158 public void getIccCardStatus(Message result) { 159 if(mIccCardStatus!=null) { 160 resultSuccess(result, mIccCardStatus); 161 } else { 162 resultFail(result, null, new RuntimeException("IccCardStatus not set")); 163 } 164 } 165 166 @Override 167 public void supplyIccPin(String pin, Message result) { 168 if (mSimLockedState != SimLockState.REQUIRE_PIN) { 169 Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin: wrong state, state=" + 170 mSimLockedState); 171 CommandException ex = new CommandException( 172 CommandException.Error.PASSWORD_INCORRECT); 173 resultFail(result, null, ex); 174 return; 175 } 176 177 if (pin != null && pin.equals(mPinCode)) { 178 Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin: success!"); 179 mPinUnlockAttempts = 0; 180 mSimLockedState = SimLockState.NONE; 181 mIccStatusChangedRegistrants.notifyRegistrants(); 182 183 resultSuccess(result, null); 184 185 return; 186 } 187 188 if (result != null) { 189 mPinUnlockAttempts ++; 190 191 Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin: failed! attempt=" + 192 mPinUnlockAttempts); 193 if (mPinUnlockAttempts >= DEFAULT_PIN1_ATTEMPT) { 194 Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin: set state to REQUIRE_PUK"); 195 mSimLockedState = SimLockState.REQUIRE_PUK; 196 } 197 198 CommandException ex = new CommandException( 199 CommandException.Error.PASSWORD_INCORRECT); 200 resultFail(result, null, ex); 201 } 202 } 203 204 @Override 205 public void supplyIccPuk(String puk, String newPin, Message result) { 206 if (mSimLockedState != SimLockState.REQUIRE_PUK) { 207 Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk: wrong state, state=" + 208 mSimLockedState); 209 CommandException ex = new CommandException( 210 CommandException.Error.PASSWORD_INCORRECT); 211 resultFail(result, null, ex); 212 return; 213 } 214 215 if (puk != null && puk.equals(SIM_PUK_CODE)) { 216 Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk: success!"); 217 mSimLockedState = SimLockState.NONE; 218 mPukUnlockAttempts = 0; 219 mIccStatusChangedRegistrants.notifyRegistrants(); 220 221 resultSuccess(result, null); 222 return; 223 } 224 225 if (result != null) { 226 mPukUnlockAttempts ++; 227 228 Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk: failed! attempt=" + 229 mPukUnlockAttempts); 230 if (mPukUnlockAttempts >= 10) { 231 Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk: set state to SIM_PERM_LOCKED"); 232 mSimLockedState = SimLockState.SIM_PERM_LOCKED; 233 } 234 235 CommandException ex = new CommandException( 236 CommandException.Error.PASSWORD_INCORRECT); 237 resultFail(result, null, ex); 238 } 239 } 240 241 @Override 242 public void supplyIccPin2(String pin2, Message result) { 243 if (mSimFdnEnabledState != SimFdnState.REQUIRE_PIN2) { 244 Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin2: wrong state, state=" + 245 mSimFdnEnabledState); 246 CommandException ex = new CommandException( 247 CommandException.Error.PASSWORD_INCORRECT); 248 resultFail(result, null, ex); 249 return; 250 } 251 252 if (pin2 != null && pin2.equals(mPin2Code)) { 253 Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin2: success!"); 254 mPin2UnlockAttempts = 0; 255 mSimFdnEnabledState = SimFdnState.NONE; 256 257 resultSuccess(result, null); 258 return; 259 } 260 261 if (result != null) { 262 mPin2UnlockAttempts ++; 263 264 Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin2: failed! attempt=" + 265 mPin2UnlockAttempts); 266 if (mPin2UnlockAttempts >= DEFAULT_PIN2_ATTEMPT) { 267 Rlog.i(LOG_TAG, "[SimCmd] supplyIccPin2: set state to REQUIRE_PUK2"); 268 mSimFdnEnabledState = SimFdnState.REQUIRE_PUK2; 269 } 270 271 CommandException ex = new CommandException( 272 CommandException.Error.PASSWORD_INCORRECT); 273 resultFail(result, null, ex); 274 } 275 } 276 277 @Override 278 public void supplyIccPuk2(String puk2, String newPin2, Message result) { 279 if (mSimFdnEnabledState != SimFdnState.REQUIRE_PUK2) { 280 Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk2: wrong state, state=" + 281 mSimLockedState); 282 CommandException ex = new CommandException( 283 CommandException.Error.PASSWORD_INCORRECT); 284 resultFail(result, null, ex); 285 return; 286 } 287 288 if (puk2 != null && puk2.equals(SIM_PUK2_CODE)) { 289 Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk2: success!"); 290 mSimFdnEnabledState = SimFdnState.NONE; 291 mPuk2UnlockAttempts = 0; 292 293 resultSuccess(result, null); 294 return; 295 } 296 297 if (result != null) { 298 mPuk2UnlockAttempts ++; 299 300 Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk2: failed! attempt=" + 301 mPuk2UnlockAttempts); 302 if (mPuk2UnlockAttempts >= 10) { 303 Rlog.i(LOG_TAG, "[SimCmd] supplyIccPuk2: set state to SIM_PERM_LOCKED"); 304 mSimFdnEnabledState = SimFdnState.SIM_PERM_LOCKED; 305 } 306 307 CommandException ex = new CommandException( 308 CommandException.Error.PASSWORD_INCORRECT); 309 resultFail(result, null, ex); 310 } 311 } 312 313 @Override 314 public void changeIccPin(String oldPin, String newPin, Message result) { 315 if (oldPin != null && oldPin.equals(mPinCode)) { 316 mPinCode = newPin; 317 resultSuccess(result, null); 318 319 return; 320 } 321 322 Rlog.i(LOG_TAG, "[SimCmd] changeIccPin: pin failed!"); 323 324 CommandException ex = new CommandException( 325 CommandException.Error.PASSWORD_INCORRECT); 326 resultFail(result, null, ex); 327 } 328 329 @Override 330 public void changeIccPin2(String oldPin2, String newPin2, Message result) { 331 if (oldPin2 != null && oldPin2.equals(mPin2Code)) { 332 mPin2Code = newPin2; 333 resultSuccess(result, null); 334 335 return; 336 } 337 338 Rlog.i(LOG_TAG, "[SimCmd] changeIccPin2: pin2 failed!"); 339 340 CommandException ex = new CommandException( 341 CommandException.Error.PASSWORD_INCORRECT); 342 resultFail(result, null, ex); 343 } 344 345 @Override 346 public void 347 changeBarringPassword(String facility, String oldPwd, String newPwd, Message result) { 348 unimplemented(result); 349 } 350 351 @Override 352 public void 353 setSuppServiceNotifications(boolean enable, Message result) { 354 resultSuccess(result, null); 355 356 if (enable && mSsnNotifyOn) { 357 Rlog.w(LOG_TAG, "Supp Service Notifications already enabled!"); 358 } 359 360 mSsnNotifyOn = enable; 361 } 362 363 @Override 364 public void queryFacilityLock(String facility, String pin, 365 int serviceClass, Message result) { 366 queryFacilityLockForApp(facility, pin, serviceClass, null, result); 367 } 368 369 @Override 370 public void queryFacilityLockForApp(String facility, String pin, int serviceClass, 371 String appId, Message result) { 372 if (facility != null && facility.equals(CommandsInterface.CB_FACILITY_BA_SIM)) { 373 if (result != null) { 374 int[] r = new int[1]; 375 r[0] = (mSimLockEnabled ? 1 : 0); 376 Rlog.i(LOG_TAG, "[SimCmd] queryFacilityLock: SIM is " 377 + (r[0] == 0 ? "unlocked" : "locked")); 378 resultSuccess(result, r); 379 } 380 return; 381 } else if (facility != null && facility.equals(CommandsInterface.CB_FACILITY_BA_FD)) { 382 if (result != null) { 383 int[] r = new int[1]; 384 r[0] = (mSimFdnEnabled ? 1 : 0); 385 Rlog.i(LOG_TAG, "[SimCmd] queryFacilityLock: FDN is " 386 + (r[0] == 0 ? "disabled" : "enabled")); 387 resultSuccess(result, r); 388 } 389 return; 390 } 391 392 unimplemented(result); 393 } 394 395 @Override 396 public void setFacilityLock(String facility, boolean lockEnabled, String pin, int serviceClass, 397 Message result) { 398 setFacilityLockForApp(facility, lockEnabled, pin, serviceClass, null, result); 399 } 400 401 @Override 402 public void setFacilityLockForApp(String facility, boolean lockEnabled, 403 String pin, int serviceClass, String appId, 404 Message result) { 405 if (facility != null && 406 facility.equals(CommandsInterface.CB_FACILITY_BA_SIM)) { 407 if (pin != null && pin.equals(mPinCode)) { 408 Rlog.i(LOG_TAG, "[SimCmd] setFacilityLock: pin is valid"); 409 mSimLockEnabled = lockEnabled; 410 411 resultSuccess(result, null); 412 413 return; 414 } 415 416 Rlog.i(LOG_TAG, "[SimCmd] setFacilityLock: pin failed!"); 417 418 CommandException ex = new CommandException( 419 CommandException.Error.GENERIC_FAILURE); 420 resultFail(result, null, ex); 421 422 return; 423 } else if (facility != null && 424 facility.equals(CommandsInterface.CB_FACILITY_BA_FD)) { 425 if (pin != null && pin.equals(mPin2Code)) { 426 Rlog.i(LOG_TAG, "[SimCmd] setFacilityLock: pin2 is valid"); 427 mSimFdnEnabled = lockEnabled; 428 429 resultSuccess(result, null); 430 431 return; 432 } 433 434 Rlog.i(LOG_TAG, "[SimCmd] setFacilityLock: pin2 failed!"); 435 436 CommandException ex = new CommandException( 437 CommandException.Error.GENERIC_FAILURE); 438 resultFail(result, null, ex); 439 440 return; 441 } 442 443 unimplemented(result); 444 } 445 446 @Override 447 public void supplyNetworkDepersonalization(String netpin, Message result) { 448 unimplemented(result); 449 } 450 451 /** 452 * returned message 453 * retMsg.obj = AsyncResult ar 454 * ar.exception carries exception on failure 455 * ar.userObject contains the original value of result.obj 456 * ar.result contains a List of DriverCall 457 * The ar.result List is sorted by DriverCall.index 458 */ 459 @Override 460 public void getCurrentCalls (Message result) { 461 SimulatedCommandsVerifier.getInstance().getCurrentCalls(result); 462 if ((mState == RadioState.RADIO_ON) && !isSimLocked()) { 463 //Rlog.i("GSM", "[SimCmds] getCurrentCalls"); 464 resultSuccess(result, simulatedCallState.getDriverCalls()); 465 } else { 466 //Rlog.i("GSM", "[SimCmds] getCurrentCalls: RADIO_OFF or SIM not ready!"); 467 resultFail(result, null, 468 new CommandException(CommandException.Error.RADIO_NOT_AVAILABLE)); 469 } 470 } 471 472 /** 473 * @deprecated 474 */ 475 @Deprecated 476 @Override 477 public void getPDPContextList(Message result) { 478 getDataCallList(result); 479 } 480 481 /** 482 * returned message 483 * retMsg.obj = AsyncResult ar 484 * ar.exception carries exception on failure 485 * ar.userObject contains the original value of result.obj 486 * ar.result contains a List of DataCallResponse 487 */ 488 @Override 489 public void getDataCallList(Message result) { 490 resultSuccess(result, new ArrayList<DataCallResponse>(0)); 491 } 492 493 /** 494 * returned message 495 * retMsg.obj = AsyncResult ar 496 * ar.exception carries exception on failure 497 * ar.userObject contains the original value of result.obj 498 * ar.result is null on success and failure 499 * 500 * CLIR_DEFAULT == on "use subscription default value" 501 * CLIR_SUPPRESSION == on "CLIR suppression" (allow CLI presentation) 502 * CLIR_INVOCATION == on "CLIR invocation" (restrict CLI presentation) 503 */ 504 @Override 505 public void dial (String address, int clirMode, Message result) { 506 SimulatedCommandsVerifier.getInstance().dial(address, clirMode, result); 507 simulatedCallState.onDial(address); 508 509 resultSuccess(result, null); 510 } 511 512 /** 513 * returned message 514 * retMsg.obj = AsyncResult ar 515 * ar.exception carries exception on failure 516 * ar.userObject contains the original value of result.obj 517 * ar.result is null on success and failure 518 * 519 * CLIR_DEFAULT == on "use subscription default value" 520 * CLIR_SUPPRESSION == on "CLIR suppression" (allow CLI presentation) 521 * CLIR_INVOCATION == on "CLIR invocation" (restrict CLI presentation) 522 */ 523 @Override 524 public void dial(String address, int clirMode, UUSInfo uusInfo, Message result) { 525 SimulatedCommandsVerifier.getInstance().dial(address, clirMode, uusInfo, result); 526 simulatedCallState.onDial(address); 527 528 resultSuccess(result, null); 529 } 530 531 @Override 532 public void getIMSI(Message result) { 533 getIMSIForApp(null, result); 534 } 535 /** 536 * returned message 537 * retMsg.obj = AsyncResult ar 538 * ar.exception carries exception on failure 539 * ar.userObject contains the original value of result.obj 540 * ar.result is String containing IMSI on success 541 */ 542 @Override 543 public void getIMSIForApp(String aid, Message result) { 544 resultSuccess(result, "012345678901234"); 545 } 546 547 public void setIMEI(String imei) { 548 mImei = imei; 549 } 550 551 /** 552 * returned message 553 * retMsg.obj = AsyncResult ar 554 * ar.exception carries exception on failure 555 * ar.userObject contains the original value of result.obj 556 * ar.result is String containing IMEI on success 557 */ 558 @Override 559 public void getIMEI(Message result) { 560 SimulatedCommandsVerifier.getInstance().getIMEI(result); 561 resultSuccess(result, mImei != null ? mImei : FAKE_IMEI); 562 } 563 564 public void setIMEISV(String imeisv) { 565 mImeiSv = imeisv; 566 } 567 568 /** 569 * returned message 570 * retMsg.obj = AsyncResult ar 571 * ar.exception carries exception on failure 572 * ar.userObject contains the original value of result.obj 573 * ar.result is String containing IMEISV on success 574 */ 575 @Override 576 public void getIMEISV(Message result) { 577 SimulatedCommandsVerifier.getInstance().getIMEISV(result); 578 resultSuccess(result, mImeiSv != null ? mImeiSv : FAKE_IMEISV); 579 } 580 581 /** 582 * Hang up one individual connection. 583 * returned message 584 * retMsg.obj = AsyncResult ar 585 * ar.exception carries exception on failure 586 * ar.userObject contains the original value of result.obj 587 * ar.result is null on success and failure 588 * 589 * 3GPP 22.030 6.5.5 590 * "Releases a specific active call X" 591 */ 592 @Override 593 public void hangupConnection (int gsmIndex, Message result) { 594 boolean success; 595 596 success = simulatedCallState.onChld('1', (char)('0'+gsmIndex)); 597 598 if (!success){ 599 Rlog.i("GSM", "[SimCmd] hangupConnection: resultFail"); 600 resultFail(result, null, new RuntimeException("Hangup Error")); 601 } else { 602 Rlog.i("GSM", "[SimCmd] hangupConnection: resultSuccess"); 603 resultSuccess(result, null); 604 } 605 } 606 607 /** 608 * 3GPP 22.030 6.5.5 609 * "Releases all held calls or sets User Determined User Busy (UDUB) 610 * for a waiting call." 611 * ar.exception carries exception on failure 612 * ar.userObject contains the original value of result.obj 613 * ar.result is null on success and failure 614 */ 615 @Override 616 public void hangupWaitingOrBackground (Message result) { 617 boolean success; 618 619 success = simulatedCallState.onChld('0', '\0'); 620 621 if (!success){ 622 resultFail(result, null, new RuntimeException("Hangup Error")); 623 } else { 624 resultSuccess(result, null); 625 } 626 } 627 628 /** 629 * 3GPP 22.030 6.5.5 630 * "Releases all active calls (if any exist) and accepts 631 * the other (held or waiting) call." 632 * 633 * ar.exception carries exception on failure 634 * ar.userObject contains the original value of result.obj 635 * ar.result is null on success and failure 636 */ 637 @Override 638 public void hangupForegroundResumeBackground (Message result) { 639 boolean success; 640 641 success = simulatedCallState.onChld('1', '\0'); 642 643 if (!success){ 644 resultFail(result, null, new RuntimeException("Hangup Error")); 645 } else { 646 resultSuccess(result, null); 647 } 648 } 649 650 /** 651 * 3GPP 22.030 6.5.5 652 * "Places all active calls (if any exist) on hold and accepts 653 * the other (held or waiting) call." 654 * 655 * ar.exception carries exception on failure 656 * ar.userObject contains the original value of result.obj 657 * ar.result is null on success and failure 658 */ 659 @Override 660 public void switchWaitingOrHoldingAndActive (Message result) { 661 boolean success; 662 663 success = simulatedCallState.onChld('2', '\0'); 664 665 if (!success){ 666 resultFail(result, null, new RuntimeException("Hangup Error")); 667 } else { 668 resultSuccess(result, null); 669 } 670 } 671 672 /** 673 * 3GPP 22.030 6.5.5 674 * "Adds a held call to the conversation" 675 * 676 * ar.exception carries exception on failure 677 * ar.userObject contains the original value of result.obj 678 * ar.result is null on success and failure 679 */ 680 @Override 681 public void conference (Message result) { 682 boolean success; 683 684 success = simulatedCallState.onChld('3', '\0'); 685 686 if (!success){ 687 resultFail(result, null, new RuntimeException("Hangup Error")); 688 } else { 689 resultSuccess(result, null); 690 } 691 } 692 693 /** 694 * 3GPP 22.030 6.5.5 695 * "Connects the two calls and disconnects the subscriber from both calls" 696 * 697 * ar.exception carries exception on failure 698 * ar.userObject contains the original value of result.obj 699 * ar.result is null on success and failure 700 */ 701 @Override 702 public void explicitCallTransfer (Message result) { 703 boolean success; 704 705 success = simulatedCallState.onChld('4', '\0'); 706 707 if (!success){ 708 resultFail(result, null, new RuntimeException("Hangup Error")); 709 } else { 710 resultSuccess(result, null); 711 } 712 } 713 714 /** 715 * 3GPP 22.030 6.5.5 716 * "Places all active calls on hold except call X with which 717 * communication shall be supported." 718 */ 719 @Override 720 public void separateConnection (int gsmIndex, Message result) { 721 boolean success; 722 723 char ch = (char)(gsmIndex + '0'); 724 success = simulatedCallState.onChld('2', ch); 725 726 if (!success){ 727 resultFail(result, null, new RuntimeException("Hangup Error")); 728 } else { 729 resultSuccess(result, null); 730 } 731 } 732 733 /** 734 * 735 * ar.exception carries exception on failure 736 * ar.userObject contains the original value of result.obj 737 * ar.result is null on success and failure 738 */ 739 @Override 740 public void acceptCall (Message result) { 741 boolean success; 742 743 SimulatedCommandsVerifier.getInstance().acceptCall(result); 744 success = simulatedCallState.onAnswer(); 745 746 if (!success){ 747 resultFail(result, null, new RuntimeException("Hangup Error")); 748 } else { 749 resultSuccess(result, null); 750 } 751 } 752 753 /** 754 * also known as UDUB 755 * ar.exception carries exception on failure 756 * ar.userObject contains the original value of result.obj 757 * ar.result is null on success and failure 758 */ 759 @Override 760 public void rejectCall (Message result) { 761 boolean success; 762 763 success = simulatedCallState.onChld('0', '\0'); 764 765 if (!success){ 766 resultFail(result, null, new RuntimeException("Hangup Error")); 767 } else { 768 resultSuccess(result, null); 769 } 770 } 771 772 /** 773 * cause code returned as Integer in Message.obj.response 774 * Returns integer cause code defined in TS 24.008 775 * Annex H or closest approximation. 776 * Most significant codes: 777 * - Any defined in 22.001 F.4 (for generating busy/congestion) 778 * - Cause 68: ACM >= ACMMax 779 */ 780 @Override 781 public void getLastCallFailCause (Message result) { 782 LastCallFailCause mFailCause = new LastCallFailCause(); 783 mFailCause.causeCode = mNextCallFailCause; 784 resultSuccess(result, mFailCause); 785 } 786 787 /** 788 * @deprecated 789 */ 790 @Deprecated 791 @Override 792 public void getLastPdpFailCause (Message result) { 793 unimplemented(result); 794 } 795 796 @Override 797 public void getLastDataCallFailCause(Message result) { 798 // 799 unimplemented(result); 800 } 801 802 @Override 803 public void setMute (boolean enableMute, Message result) {unimplemented(result);} 804 805 @Override 806 public void getMute (Message result) {unimplemented(result);} 807 808 public void setSignalStrength(SignalStrength signalStrength) { 809 mSignalStrength = signalStrength; 810 } 811 812 @Override 813 public void getSignalStrength (Message result) { 814 815 if (mSignalStrength == null) { 816 mSignalStrength = new SignalStrength( 817 20, // gsmSignalStrength 818 0, // gsmBitErrorRate 819 -1, // cdmaDbm 820 -1, // cdmaEcio 821 -1, // evdoDbm 822 -1, // evdoEcio 823 -1, // evdoSnr 824 99, // lteSignalStrength 825 SignalStrength.INVALID, // lteRsrp 826 SignalStrength.INVALID, // lteRsrq 827 SignalStrength.INVALID, // lteRssnr 828 SignalStrength.INVALID, // lteCqi 829 SignalStrength.INVALID, // tdScdmaRscp 830 true // gsmFlag 831 ); 832 } 833 834 resultSuccess(result, mSignalStrength); 835 } 836 837 /** 838 * Assign a specified band for RF configuration. 839 * 840 * @param bandMode one of BM_*_BAND 841 * @param result is callback message 842 */ 843 @Override 844 public void setBandMode (int bandMode, Message result) { 845 resultSuccess(result, null); 846 } 847 848 /** 849 * Query the list of band mode supported by RF. 850 * 851 * @param result is callback message 852 * ((AsyncResult)response.obj).result is an int[] where int[0] is 853 * the size of the array and the rest of each element representing 854 * one available BM_*_BAND 855 */ 856 @Override 857 public void queryAvailableBandMode (Message result) { 858 int ret[] = new int [4]; 859 860 ret[0] = 4; 861 ret[1] = Phone.BM_US_BAND; 862 ret[2] = Phone.BM_JPN_BAND; 863 ret[3] = Phone.BM_AUS_BAND; 864 865 resultSuccess(result, ret); 866 } 867 868 /** 869 * {@inheritDoc} 870 */ 871 @Override 872 public void sendTerminalResponse(String contents, Message response) { 873 resultSuccess(response, null); 874 } 875 876 /** 877 * {@inheritDoc} 878 */ 879 @Override 880 public void sendEnvelope(String contents, Message response) { 881 resultSuccess(response, null); 882 } 883 884 /** 885 * {@inheritDoc} 886 */ 887 @Override 888 public void sendEnvelopeWithStatus(String contents, Message response) { 889 resultSuccess(response, null); 890 } 891 892 /** 893 * {@inheritDoc} 894 */ 895 @Override 896 public void handleCallSetupRequestFromSim( 897 boolean accept, Message response) { 898 resultSuccess(response, null); 899 } 900 901 public void setVoiceRadioTech(int voiceRadioTech) { 902 mVoiceRadioTech = voiceRadioTech; 903 } 904 905 public void setVoiceRegState(int voiceRegState) { 906 mVoiceRegState = voiceRegState; 907 } 908 909 /** 910 * response.obj.result is an String[14] 911 * See ril.h for details 912 * 913 * Please note that registration state 4 ("unknown") is treated 914 * as "out of service" above 915 */ 916 @Override 917 public void getVoiceRegistrationState(Message result) { 918 mGetVoiceRegistrationStateCallCount.incrementAndGet(); 919 String ret[] = new String[14]; 920 921 ret[0] = Integer.toString(mVoiceRegState); 922 ret[3] = Integer.toString(mVoiceRadioTech); 923 924 resultSuccess(result, ret); 925 } 926 927 private final AtomicInteger mGetVoiceRegistrationStateCallCount = new AtomicInteger(0); 928 929 @VisibleForTesting 930 public int getGetVoiceRegistrationStateCallCount() { 931 return mGetVoiceRegistrationStateCallCount.get(); 932 } 933 934 public void setDataRadioTech(int radioTech) { 935 mDataRadioTech = radioTech; 936 } 937 938 public void setDataRegState(int dataRegState) { 939 mDataRegState = dataRegState; 940 } 941 942 @Override 943 public void getDataRegistrationState (Message result) { 944 mGetDataRegistrationStateCallCount.incrementAndGet(); 945 String ret[] = new String[11]; 946 947 ret[0] = Integer.toString(mDataRegState); 948 ret[3] = Integer.toString(mDataRadioTech); 949 950 resultSuccess(result, ret); 951 } 952 953 private final AtomicInteger mGetDataRegistrationStateCallCount = new AtomicInteger(0); 954 955 @VisibleForTesting 956 public int getGetDataRegistrationStateCallCount() { 957 return mGetDataRegistrationStateCallCount.get(); 958 } 959 960 /** 961 * response.obj.result is a String[3] 962 * response.obj.result[0] is long alpha or null if unregistered 963 * response.obj.result[1] is short alpha or null if unregistered 964 * response.obj.result[2] is numeric or null if unregistered 965 */ 966 @Override 967 public void getOperator(Message result) { 968 mGetOperatorCallCount.incrementAndGet(); 969 String[] ret = new String[3]; 970 971 ret[0] = FAKE_LONG_NAME; 972 ret[1] = FAKE_SHORT_NAME; 973 ret[2] = FAKE_MCC_MNC; 974 975 resultSuccess(result, ret); 976 } 977 978 private final AtomicInteger mGetOperatorCallCount = new AtomicInteger(0); 979 980 @VisibleForTesting 981 public int getGetOperatorCallCount() { 982 final int count = mGetOperatorCallCount.get(); 983 return mGetOperatorCallCount.get(); 984 } 985 986 /** 987 * ar.exception carries exception on failure 988 * ar.userObject contains the original value of result.obj 989 * ar.result is null on success and failure 990 */ 991 @Override 992 public void sendDtmf(char c, Message result) { 993 resultSuccess(result, null); 994 } 995 996 /** 997 * ar.exception carries exception on failure 998 * ar.userObject contains the original value of result.obj 999 * ar.result is null on success and failure 1000 */ 1001 @Override 1002 public void startDtmf(char c, Message result) { 1003 resultSuccess(result, null); 1004 } 1005 1006 /** 1007 * ar.exception carries exception on failure 1008 * ar.userObject contains the original value of result.obj 1009 * ar.result is null on success and failure 1010 */ 1011 @Override 1012 public void stopDtmf(Message result) { 1013 resultSuccess(result, null); 1014 } 1015 1016 /** 1017 * ar.exception carries exception on failure 1018 * ar.userObject contains the original value of result.obj 1019 * ar.result is null on success and failure 1020 */ 1021 @Override 1022 public void sendBurstDtmf(String dtmfString, int on, int off, Message result) { 1023 SimulatedCommandsVerifier.getInstance().sendBurstDtmf(dtmfString, on, off, result); 1024 resultSuccess(result, null); 1025 } 1026 1027 /** 1028 * smscPDU is smsc address in PDU form GSM BCD format prefixed 1029 * by a length byte (as expected by TS 27.005) or NULL for default SMSC 1030 * pdu is SMS in PDU format as an ASCII hex string 1031 * less the SMSC address 1032 */ 1033 @Override 1034 public void sendSMS (String smscPDU, String pdu, Message result) { 1035 SimulatedCommandsVerifier.getInstance().sendSMS(smscPDU, pdu, result); 1036 resultSuccess(result, new SmsResponse(0 /*messageRef*/, null, 0)); 1037 } 1038 1039 /** 1040 * Send an SMS message, Identical to sendSMS, 1041 * except that more messages are expected to be sent soon 1042 * smscPDU is smsc address in PDU form GSM BCD format prefixed 1043 * by a length byte (as expected by TS 27.005) or NULL for default SMSC 1044 * pdu is SMS in PDU format as an ASCII hex string 1045 * less the SMSC address 1046 */ 1047 @Override 1048 public void sendSMSExpectMore (String smscPDU, String pdu, Message result) { 1049 unimplemented(result); 1050 } 1051 1052 @Override 1053 public void deleteSmsOnSim(int index, Message response) { 1054 Rlog.d(LOG_TAG, "Delete message at index " + index); 1055 unimplemented(response); 1056 } 1057 1058 @Override 1059 public void deleteSmsOnRuim(int index, Message response) { 1060 Rlog.d(LOG_TAG, "Delete RUIM message at index " + index); 1061 unimplemented(response); 1062 } 1063 1064 @Override 1065 public void writeSmsToSim(int status, String smsc, String pdu, Message response) { 1066 Rlog.d(LOG_TAG, "Write SMS to SIM with status " + status); 1067 unimplemented(response); 1068 } 1069 1070 @Override 1071 public void writeSmsToRuim(int status, String pdu, Message response) { 1072 Rlog.d(LOG_TAG, "Write SMS to RUIM with status " + status); 1073 unimplemented(response); 1074 } 1075 1076 public void setDataCallResponse(final boolean success, final DataCallResponse dcResponse) { 1077 mDcResponse = dcResponse; 1078 mDcSuccess = success; 1079 } 1080 1081 public void triggerNITZupdate(String NITZStr) { 1082 if (NITZStr != null) { 1083 mNITZTimeRegistrant.notifyRegistrant(new AsyncResult (null, new Object[]{NITZStr, 1084 SystemClock.elapsedRealtime()}, null)); 1085 } 1086 } 1087 1088 @Override 1089 public void setupDataCall(int radioTechnology, int profile, 1090 String apn, String user, String password, int authType, 1091 String protocol, Message result) { 1092 SimulatedCommandsVerifier.getInstance().setupDataCall(radioTechnology, profile, apn, user, 1093 password, authType, protocol, result); 1094 1095 if (mDcResponse == null) { 1096 mDcResponse = new DataCallResponse(); 1097 mDcResponse.version = 11; 1098 mDcResponse.status = 0; 1099 mDcResponse.suggestedRetryTime = -1; 1100 mDcResponse.cid = 1; 1101 mDcResponse.active = 2; 1102 mDcResponse.type = "IP"; 1103 mDcResponse.ifname = "rmnet_data7"; 1104 mDcResponse.mtu = 1440; 1105 mDcResponse.addresses = new String[]{"12.34.56.78"}; 1106 mDcResponse.dnses = new String[]{"98.76.54.32"}; 1107 mDcResponse.gateways = new String[]{"11.22.33.44"}; 1108 mDcResponse.pcscf = new String[]{}; 1109 } 1110 1111 if (mDcSuccess) { 1112 resultSuccess(result, mDcResponse); 1113 } else { 1114 resultFail(result, mDcResponse, new RuntimeException("Setup data call failed!")); 1115 } 1116 } 1117 1118 @Override 1119 public void deactivateDataCall(int cid, int reason, Message result) { 1120 SimulatedCommandsVerifier.getInstance().deactivateDataCall(cid, reason, result); 1121 resultSuccess(result, null); 1122 } 1123 1124 @Override 1125 public void setPreferredNetworkType(int networkType , Message result) { 1126 SimulatedCommandsVerifier.getInstance().setPreferredNetworkType(networkType, result); 1127 mNetworkType = networkType; 1128 resultSuccess(result, null); 1129 } 1130 1131 @Override 1132 public void getPreferredNetworkType(Message result) { 1133 SimulatedCommandsVerifier.getInstance().getPreferredNetworkType(result); 1134 int ret[] = new int[1]; 1135 1136 ret[0] = mNetworkType; 1137 resultSuccess(result, ret); 1138 } 1139 1140 @Override 1141 public void getNeighboringCids(Message result) { 1142 int ret[] = new int[7]; 1143 1144 ret[0] = 6; 1145 for (int i = 1; i<7; i++) { 1146 ret[i] = i; 1147 } 1148 resultSuccess(result, ret); 1149 } 1150 1151 @Override 1152 public void setLocationUpdates(boolean enable, Message response) { 1153 SimulatedCommandsVerifier.getInstance().setLocationUpdates(enable, response); 1154 resultSuccess(response, null); 1155 } 1156 1157 @Override 1158 public void getSmscAddress(Message result) { 1159 unimplemented(result); 1160 } 1161 1162 @Override 1163 public void setSmscAddress(String address, Message result) { 1164 unimplemented(result); 1165 } 1166 1167 @Override 1168 public void reportSmsMemoryStatus(boolean available, Message result) { 1169 resultSuccess(result, null); 1170 SimulatedCommandsVerifier.getInstance().reportSmsMemoryStatus(available, result); 1171 } 1172 1173 @Override 1174 public void reportStkServiceIsRunning(Message result) { 1175 resultSuccess(result, null); 1176 } 1177 1178 @Override 1179 public void getCdmaSubscriptionSource(Message result) { 1180 unimplemented(result); 1181 } 1182 1183 private boolean isSimLocked() { 1184 if (mSimLockedState != SimLockState.NONE) { 1185 return true; 1186 } 1187 return false; 1188 } 1189 1190 @Override 1191 public void setRadioPower(boolean on, Message result) { 1192 if(on) { 1193 setRadioState(RadioState.RADIO_ON); 1194 } else { 1195 setRadioState(RadioState.RADIO_OFF); 1196 } 1197 } 1198 1199 1200 @Override 1201 public void acknowledgeLastIncomingGsmSms(boolean success, int cause, Message result) { 1202 unimplemented(result); 1203 SimulatedCommandsVerifier.getInstance(). 1204 acknowledgeLastIncomingGsmSms(success, cause, result); 1205 } 1206 1207 @Override 1208 public void acknowledgeLastIncomingCdmaSms(boolean success, int cause, Message result) { 1209 unimplemented(result); 1210 } 1211 1212 @Override 1213 public void acknowledgeIncomingGsmSmsWithPdu(boolean success, String ackPdu, 1214 Message result) { 1215 unimplemented(result); 1216 } 1217 1218 @Override 1219 public void iccIO(int command, int fileid, String path, int p1, int p2, int p3, String data, 1220 String pin2, Message response) { 1221 iccIOForApp(command, fileid, path, p1, p2, p3, data, pin2, null, response); 1222 } 1223 1224 /** 1225 * parameters equivalent to 27.007 AT+CRSM command 1226 * response.obj will be an AsyncResult 1227 * response.obj.userObj will be a SimIoResult on success 1228 */ 1229 @Override 1230 public void iccIOForApp (int command, int fileid, String path, int p1, int p2, 1231 int p3, String data, String pin2, String aid, Message result) { 1232 unimplemented(result); 1233 } 1234 1235 /** 1236 * (AsyncResult)response.obj).result is an int[] with element [0] set to 1237 * 1 for "CLIP is provisioned", and 0 for "CLIP is not provisioned". 1238 * 1239 * @param response is callback message 1240 */ 1241 @Override 1242 public void queryCLIP(Message response) { unimplemented(response); } 1243 1244 1245 /** 1246 * response.obj will be a an int[2] 1247 * 1248 * response.obj[0] will be TS 27.007 +CLIR parameter 'n' 1249 * 0 presentation indicator is used according to the subscription of the CLIR service 1250 * 1 CLIR invocation 1251 * 2 CLIR suppression 1252 * 1253 * response.obj[1] will be TS 27.007 +CLIR parameter 'm' 1254 * 0 CLIR not provisioned 1255 * 1 CLIR provisioned in permanent mode 1256 * 2 unknown (e.g. no network, etc.) 1257 * 3 CLIR temporary mode presentation restricted 1258 * 4 CLIR temporary mode presentation allowed 1259 */ 1260 1261 @Override 1262 public void getCLIR(Message result) {unimplemented(result);} 1263 1264 /** 1265 * clirMode is one of the CLIR_* constants above 1266 * 1267 * response.obj is null 1268 */ 1269 1270 @Override 1271 public void setCLIR(int clirMode, Message result) {unimplemented(result);} 1272 1273 /** 1274 * (AsyncResult)response.obj).result is an int[] with element [0] set to 1275 * 0 for disabled, 1 for enabled. 1276 * 1277 * @param serviceClass is a sum of SERVICE_CLASS_* 1278 * @param response is callback message 1279 */ 1280 1281 @Override 1282 public void queryCallWaiting(int serviceClass, Message response) { 1283 unimplemented(response); 1284 } 1285 1286 /** 1287 * @param enable is true to enable, false to disable 1288 * @param serviceClass is a sum of SERVICE_CLASS_* 1289 * @param response is callback message 1290 */ 1291 1292 @Override 1293 public void setCallWaiting(boolean enable, int serviceClass, 1294 Message response) { 1295 unimplemented(response); 1296 } 1297 1298 /** 1299 * @param action is one of CF_ACTION_* 1300 * @param cfReason is one of CF_REASON_* 1301 * @param serviceClass is a sum of SERVICE_CLASSS_* 1302 */ 1303 @Override 1304 public void setCallForward(int action, int cfReason, int serviceClass, 1305 String number, int timeSeconds, Message result) { 1306 SimulatedCommandsVerifier.getInstance().setCallForward(action, cfReason, serviceClass, 1307 number, timeSeconds, result); 1308 resultSuccess(result, null); 1309 } 1310 1311 /** 1312 * cfReason is one of CF_REASON_* 1313 * 1314 * ((AsyncResult)response.obj).result will be an array of 1315 * CallForwardInfo's 1316 * 1317 * An array of length 0 means "disabled for all codes" 1318 */ 1319 @Override 1320 public void queryCallForwardStatus(int cfReason, int serviceClass, 1321 String number, Message result) { 1322 SimulatedCommandsVerifier.getInstance().queryCallForwardStatus(cfReason, serviceClass, 1323 number, result); 1324 resultSuccess(result, null); 1325 } 1326 1327 @Override 1328 public void setNetworkSelectionModeAutomatic(Message result) {unimplemented(result);} 1329 @Override 1330 public void exitEmergencyCallbackMode(Message result) {unimplemented(result);} 1331 @Override 1332 public void setNetworkSelectionModeManual( 1333 String operatorNumeric, Message result) {unimplemented(result);} 1334 1335 /** 1336 * Queries whether the current network selection mode is automatic 1337 * or manual 1338 * 1339 * ((AsyncResult)response.obj).result is an int[] with element [0] being 1340 * a 0 for automatic selection and a 1 for manual selection 1341 */ 1342 1343 @Override 1344 public void getNetworkSelectionMode(Message result) { 1345 SimulatedCommandsVerifier.getInstance().getNetworkSelectionMode(result); 1346 getNetworkSelectionModeCallCount.incrementAndGet(); 1347 int ret[] = new int[1]; 1348 1349 ret[0] = 0; 1350 resultSuccess(result, ret); 1351 } 1352 1353 private final AtomicInteger getNetworkSelectionModeCallCount = new AtomicInteger(0); 1354 1355 @VisibleForTesting 1356 public int getGetNetworkSelectionModeCallCount() { 1357 return getNetworkSelectionModeCallCount.get(); 1358 } 1359 1360 /** 1361 * Queries the currently available networks 1362 * 1363 * ((AsyncResult)response.obj).result is a List of NetworkInfo objects 1364 */ 1365 @Override 1366 public void getAvailableNetworks(Message result) {unimplemented(result);} 1367 1368 @Override 1369 public void getBasebandVersion (Message result) { 1370 SimulatedCommandsVerifier.getInstance().getBasebandVersion(result); 1371 resultSuccess(result, "SimulatedCommands"); 1372 } 1373 1374 /** 1375 * Simulates an Stk Call Control Alpha message 1376 * @param alphaString Alpha string to send. 1377 */ 1378 public void triggerIncomingStkCcAlpha(String alphaString) { 1379 if (mCatCcAlphaRegistrant != null) { 1380 mCatCcAlphaRegistrant.notifyResult(alphaString); 1381 } 1382 } 1383 1384 public void sendStkCcAplha(String alphaString) { 1385 triggerIncomingStkCcAlpha(alphaString); 1386 } 1387 1388 /** 1389 * Simulates an incoming USSD message 1390 * @param statusCode Status code string. See <code>setOnUSSD</code> 1391 * in CommandsInterface.java 1392 * @param message Message text to send or null if none 1393 */ 1394 @Override 1395 public void triggerIncomingUssd(String statusCode, String message) { 1396 if (mUSSDRegistrant != null) { 1397 String[] result = {statusCode, message}; 1398 mUSSDRegistrant.notifyResult(result); 1399 } 1400 } 1401 1402 1403 @Override 1404 public void sendUSSD (String ussdString, Message result) { 1405 1406 // We simulate this particular sequence 1407 if (ussdString.equals("#646#")) { 1408 resultSuccess(result, null); 1409 1410 // 0 == USSD-Notify 1411 triggerIncomingUssd("0", "You have NNN minutes remaining."); 1412 } else { 1413 resultSuccess(result, null); 1414 1415 triggerIncomingUssd("0", "All Done"); 1416 } 1417 } 1418 1419 // inherited javadoc suffices 1420 @Override 1421 public void cancelPendingUssd (Message response) { 1422 resultSuccess(response, null); 1423 } 1424 1425 1426 @Override 1427 public void resetRadio(Message result) { 1428 unimplemented(result); 1429 } 1430 1431 @Override 1432 public void invokeOemRilRequestRaw(byte[] data, Message response) { 1433 // Just echo back data 1434 if (response != null) { 1435 AsyncResult.forMessage(response).result = data; 1436 response.sendToTarget(); 1437 } 1438 } 1439 1440 @Override 1441 public void invokeOemRilRequestStrings(String[] strings, Message response) { 1442 // Just echo back data 1443 if (response != null) { 1444 AsyncResult.forMessage(response).result = strings; 1445 response.sendToTarget(); 1446 } 1447 } 1448 1449 //***** SimulatedRadioControl 1450 1451 1452 /** Start the simulated phone ringing */ 1453 @Override 1454 public void 1455 triggerRing(String number) { 1456 simulatedCallState.triggerRing(number); 1457 mCallStateRegistrants.notifyRegistrants(); 1458 } 1459 1460 @Override 1461 public void 1462 progressConnectingCallState() { 1463 simulatedCallState.progressConnectingCallState(); 1464 mCallStateRegistrants.notifyRegistrants(); 1465 } 1466 1467 /** If a call is DIALING or ALERTING, progress it all the way to ACTIVE */ 1468 @Override 1469 public void 1470 progressConnectingToActive() { 1471 simulatedCallState.progressConnectingToActive(); 1472 mCallStateRegistrants.notifyRegistrants(); 1473 } 1474 1475 /** automatically progress mobile originated calls to ACTIVE. 1476 * default to true 1477 */ 1478 @Override 1479 public void 1480 setAutoProgressConnectingCall(boolean b) { 1481 simulatedCallState.setAutoProgressConnectingCall(b); 1482 } 1483 1484 @Override 1485 public void 1486 setNextDialFailImmediately(boolean b) { 1487 simulatedCallState.setNextDialFailImmediately(b); 1488 } 1489 1490 @Override 1491 public void 1492 setNextCallFailCause(int gsmCause) { 1493 mNextCallFailCause = gsmCause; 1494 } 1495 1496 @Override 1497 public void 1498 triggerHangupForeground() { 1499 simulatedCallState.triggerHangupForeground(); 1500 mCallStateRegistrants.notifyRegistrants(); 1501 } 1502 1503 /** hangup holding calls */ 1504 @Override 1505 public void 1506 triggerHangupBackground() { 1507 simulatedCallState.triggerHangupBackground(); 1508 mCallStateRegistrants.notifyRegistrants(); 1509 } 1510 1511 @Override 1512 public void triggerSsn(int type, int code) { 1513 SuppServiceNotification not = new SuppServiceNotification(); 1514 not.notificationType = type; 1515 not.code = code; 1516 mSsnRegistrant.notifyRegistrant(new AsyncResult(null, not, null)); 1517 } 1518 1519 @Override 1520 public void 1521 shutdown() { 1522 setRadioState(RadioState.RADIO_UNAVAILABLE); 1523 Looper looper = mHandlerThread.getLooper(); 1524 if (looper != null) { 1525 looper.quit(); 1526 } 1527 } 1528 1529 /** hangup all */ 1530 1531 @Override 1532 public void 1533 triggerHangupAll() { 1534 simulatedCallState.triggerHangupAll(); 1535 mCallStateRegistrants.notifyRegistrants(); 1536 } 1537 1538 @Override 1539 public void 1540 triggerIncomingSMS(String message) { 1541 //TODO 1542 } 1543 1544 @Override 1545 public void 1546 pauseResponses() { 1547 mPausedResponseCount++; 1548 } 1549 1550 @Override 1551 public void 1552 resumeResponses() { 1553 mPausedResponseCount--; 1554 1555 if (mPausedResponseCount == 0) { 1556 for (int i = 0, s = mPausedResponses.size(); i < s ; i++) { 1557 mPausedResponses.get(i).sendToTarget(); 1558 } 1559 mPausedResponses.clear(); 1560 } else { 1561 Rlog.e("GSM", "SimulatedCommands.resumeResponses < 0"); 1562 } 1563 } 1564 1565 //***** Private Methods 1566 1567 private void unimplemented(Message result) { 1568 if (result != null) { 1569 AsyncResult.forMessage(result).exception 1570 = new RuntimeException("Unimplemented"); 1571 1572 if (mPausedResponseCount > 0) { 1573 mPausedResponses.add(result); 1574 } else { 1575 result.sendToTarget(); 1576 } 1577 } 1578 } 1579 1580 private void resultSuccess(Message result, Object ret) { 1581 if (result != null) { 1582 AsyncResult.forMessage(result).result = ret; 1583 if (mPausedResponseCount > 0) { 1584 mPausedResponses.add(result); 1585 } else { 1586 result.sendToTarget(); 1587 } 1588 } 1589 } 1590 1591 private void resultFail(Message result, Object ret, Throwable tr) { 1592 if (result != null) { 1593 AsyncResult.forMessage(result, ret, tr); 1594 if (mPausedResponseCount > 0) { 1595 mPausedResponses.add(result); 1596 } else { 1597 result.sendToTarget(); 1598 } 1599 } 1600 } 1601 1602 // ***** Methods for CDMA support 1603 @Override 1604 public void 1605 getDeviceIdentity(Message response) { 1606 SimulatedCommandsVerifier.getInstance().getDeviceIdentity(response); 1607 resultSuccess(response, new String[] {FAKE_IMEI, FAKE_IMEISV, FAKE_ESN, FAKE_MEID}); 1608 } 1609 1610 @Override 1611 public void 1612 getCDMASubscription(Message result) { 1613 String ret[] = new String[5]; 1614 ret[0] = "123"; 1615 ret[1] = "456"; 1616 ret[2] = "789"; 1617 ret[3] = "234"; 1618 ret[4] = "345"; 1619 resultSuccess(result, ret); 1620 } 1621 1622 @Override 1623 public void 1624 setCdmaSubscriptionSource(int cdmaSubscriptionType, Message response) { 1625 unimplemented(response); 1626 } 1627 1628 @Override 1629 public void queryCdmaRoamingPreference(Message response) { 1630 unimplemented(response); 1631 } 1632 1633 @Override 1634 public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) { 1635 unimplemented(response); 1636 } 1637 1638 @Override 1639 public void 1640 setPhoneType(int phoneType) { 1641 } 1642 1643 @Override 1644 public void getPreferredVoicePrivacy(Message result) { 1645 unimplemented(result); 1646 } 1647 1648 @Override 1649 public void setPreferredVoicePrivacy(boolean enable, Message result) { 1650 unimplemented(result); 1651 } 1652 1653 /** 1654 * Set the TTY mode 1655 * 1656 * @param ttyMode is one of the following: 1657 * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} 1658 * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} 1659 * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} 1660 * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO} 1661 * @param response is callback message 1662 */ 1663 @Override 1664 public void setTTYMode(int ttyMode, Message response) { 1665 Rlog.w(LOG_TAG, "Not implemented in SimulatedCommands"); 1666 unimplemented(response); 1667 } 1668 1669 /** 1670 * Query the TTY mode 1671 * (AsyncResult)response.obj).result is an int[] with element [0] set to 1672 * tty mode: 1673 * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} 1674 * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} 1675 * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} 1676 * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO} 1677 * @param response is callback message 1678 */ 1679 @Override 1680 public void queryTTYMode(Message response) { 1681 unimplemented(response); 1682 } 1683 1684 /** 1685 * {@inheritDoc} 1686 */ 1687 @Override 1688 public void sendCDMAFeatureCode(String FeatureCode, Message response) { 1689 unimplemented(response); 1690 } 1691 1692 /** 1693 * {@inheritDoc} 1694 */ 1695 @Override 1696 public void sendCdmaSms(byte[] pdu, Message response){ 1697 SimulatedCommandsVerifier.getInstance().sendCdmaSms(pdu, response); 1698 resultSuccess(response, null); 1699 } 1700 1701 @Override 1702 public void setCdmaBroadcastActivation(boolean activate, Message response) { 1703 unimplemented(response); 1704 1705 } 1706 1707 @Override 1708 public void getCdmaBroadcastConfig(Message response) { 1709 unimplemented(response); 1710 1711 } 1712 1713 @Override 1714 public void setCdmaBroadcastConfig(CdmaSmsBroadcastConfigInfo[] configs, Message response) { 1715 unimplemented(response); 1716 } 1717 1718 public void forceDataDormancy(Message response) { 1719 unimplemented(response); 1720 } 1721 1722 1723 @Override 1724 public void setGsmBroadcastActivation(boolean activate, Message response) { 1725 unimplemented(response); 1726 } 1727 1728 1729 @Override 1730 public void setGsmBroadcastConfig(SmsBroadcastConfigInfo[] config, Message response) { 1731 unimplemented(response); 1732 } 1733 1734 @Override 1735 public void getGsmBroadcastConfig(Message response) { 1736 unimplemented(response); 1737 } 1738 1739 @Override 1740 public void supplyIccPinForApp(String pin, String aid, Message response) { 1741 SimulatedCommandsVerifier.getInstance().supplyIccPinForApp(pin, aid, response); 1742 if (mPinCode != null && mPinCode.equals(pin)) { 1743 resultSuccess(response, null); 1744 return; 1745 } 1746 1747 Rlog.i(LOG_TAG, "[SimCmd] supplyIccPinForApp: pin failed!"); 1748 CommandException ex = new CommandException( 1749 CommandException.Error.PASSWORD_INCORRECT); 1750 resultFail(response, new int[]{ 1751 (--mPin1attemptsRemaining < 0) ? 0 : mPin1attemptsRemaining}, ex); 1752 } 1753 1754 @Override 1755 public void supplyIccPukForApp(String puk, String newPin, String aid, Message response) { 1756 unimplemented(response); 1757 } 1758 1759 @Override 1760 public void supplyIccPin2ForApp(String pin2, String aid, Message response) { 1761 unimplemented(response); 1762 } 1763 1764 @Override 1765 public void supplyIccPuk2ForApp(String puk2, String newPin2, String aid, Message response) { 1766 unimplemented(response); 1767 } 1768 1769 @Override 1770 public void changeIccPinForApp(String oldPin, String newPin, String aidPtr, Message response) { 1771 SimulatedCommandsVerifier.getInstance().changeIccPinForApp(oldPin, newPin, aidPtr, 1772 response); 1773 changeIccPin(oldPin, newPin, response); 1774 } 1775 1776 @Override 1777 public void changeIccPin2ForApp(String oldPin2, String newPin2, String aidPtr, 1778 Message response) { 1779 unimplemented(response); 1780 } 1781 1782 @Override 1783 public void requestIsimAuthentication(String nonce, Message response) { 1784 unimplemented(response); 1785 } 1786 1787 @Override 1788 public void requestIccSimAuthentication(int authContext, String data, String aid, Message response) { 1789 unimplemented(response); 1790 } 1791 1792 @Override 1793 public void getVoiceRadioTechnology(Message response) { 1794 SimulatedCommandsVerifier.getInstance().getVoiceRadioTechnology(response); 1795 int ret[] = new int[1]; 1796 ret[0] = mVoiceRadioTech; 1797 resultSuccess(response, ret); 1798 } 1799 1800 public void setCellInfoList(List<CellInfo> list) { 1801 mCellInfoList = list; 1802 } 1803 1804 @Override 1805 public void getCellInfoList(Message response) { 1806 if (mCellInfoList == null) { 1807 Parcel p = Parcel.obtain(); 1808 p.writeInt(1); 1809 p.writeInt(1); 1810 p.writeInt(2); 1811 p.writeLong(1453510289108L); 1812 p.writeInt(310); 1813 p.writeInt(260); 1814 p.writeInt(123); 1815 p.writeInt(456); 1816 p.writeInt(99); 1817 p.writeInt(3); 1818 p.setDataPosition(0); 1819 1820 CellInfoGsm cellInfo = CellInfoGsm.CREATOR.createFromParcel(p); 1821 1822 ArrayList<CellInfo> mCellInfoList = new ArrayList(); 1823 mCellInfoList.add(cellInfo); 1824 } 1825 1826 resultSuccess(response, mCellInfoList); 1827 } 1828 1829 @Override 1830 public int getRilVersion() { 1831 return 11; 1832 } 1833 1834 @Override 1835 public void setCellInfoListRate(int rateInMillis, Message response) { 1836 unimplemented(response); 1837 } 1838 1839 @Override 1840 public void setInitialAttachApn(String apn, String protocol, int authType, String username, 1841 String password, Message result) { 1842 } 1843 1844 @Override 1845 public void setDataProfile(DataProfile[] dps, Message result) { 1846 } 1847 1848 public void setImsRegistrationState(int[] regState) { 1849 mImsRegState = regState; 1850 } 1851 1852 @Override 1853 public void getImsRegistrationState(Message response) { 1854 if (mImsRegState == null) { 1855 mImsRegState = new int[]{1, PhoneConstants.PHONE_TYPE_NONE}; 1856 } 1857 1858 resultSuccess(response, mImsRegState); 1859 } 1860 1861 @Override 1862 public void sendImsCdmaSms(byte[] pdu, int retry, int messageRef, 1863 Message response){ 1864 SimulatedCommandsVerifier.getInstance().sendImsCdmaSms(pdu, retry, messageRef, response); 1865 resultSuccess(response, new SmsResponse(0 /*messageRef*/, null, 0)); 1866 } 1867 1868 @Override 1869 public void sendImsGsmSms(String smscPDU, String pdu, 1870 int retry, int messageRef, Message response){ 1871 SimulatedCommandsVerifier.getInstance().sendImsGsmSms(smscPDU, pdu, retry, messageRef, 1872 response); 1873 resultSuccess(response, new SmsResponse(0 /*messageRef*/, null, 0)); 1874 } 1875 1876 @Override 1877 public void iccOpenLogicalChannel(String AID, Message response) { 1878 SimulatedCommandsVerifier.getInstance().iccOpenLogicalChannel(AID, response); 1879 Object result = new int[]{mChannelId}; 1880 resultSuccess(response, result); 1881 } 1882 1883 @Override 1884 public void iccCloseLogicalChannel(int channel, Message response) { 1885 unimplemented(response); 1886 } 1887 1888 @Override 1889 public void iccTransmitApduLogicalChannel(int channel, int cla, int instruction, 1890 int p1, int p2, int p3, String data, 1891 Message response) { 1892 SimulatedCommandsVerifier.getInstance().iccTransmitApduLogicalChannel(channel, cla, 1893 instruction, p1, p2, p3, data, response); 1894 if(mIccIoResultForApduLogicalChannel!=null) { 1895 resultSuccess(response, mIccIoResultForApduLogicalChannel); 1896 }else { 1897 resultFail(response, null, new RuntimeException("IccIoResult not set")); 1898 } 1899 } 1900 1901 @Override 1902 public void iccTransmitApduBasicChannel(int cla, int instruction, int p1, int p2, 1903 int p3, String data, Message response) { 1904 unimplemented(response); 1905 } 1906 1907 @Override 1908 public void nvReadItem(int itemID, Message response) { 1909 unimplemented(response); 1910 } 1911 1912 @Override 1913 public void nvWriteItem(int itemID, String itemValue, Message response) { 1914 unimplemented(response); 1915 } 1916 1917 @Override 1918 public void nvWriteCdmaPrl(byte[] preferredRoamingList, Message response) { 1919 unimplemented(response); 1920 } 1921 1922 @Override 1923 public void nvResetConfig(int resetType, Message response) { 1924 unimplemented(response); 1925 } 1926 1927 @Override 1928 public void getHardwareConfig(Message result) { 1929 unimplemented(result); 1930 } 1931 1932 @Override 1933 public void requestShutdown(Message result) { 1934 setRadioState(RadioState.RADIO_UNAVAILABLE); 1935 } 1936 1937 @Override 1938 public void startLceService(int report_interval_ms, boolean pullMode, Message result) { 1939 SimulatedCommandsVerifier.getInstance().startLceService(report_interval_ms, pullMode, 1940 result); 1941 unimplemented(result); 1942 } 1943 1944 @Override 1945 public void stopLceService(Message result) { 1946 unimplemented(result); 1947 } 1948 1949 @Override 1950 public void pullLceData(Message result) { 1951 unimplemented(result); 1952 } 1953 1954 @Override 1955 public void getModemActivityInfo(Message result) { 1956 unimplemented(result); 1957 } 1958 1959 @Override 1960 public void getRadioCapability(Message result) { 1961 SimulatedCommandsVerifier.getInstance().getRadioCapability(result); 1962 resultSuccess(result, new RadioCapability(0, 0, 0, 0xFFFF, null, 0)); 1963 } 1964 public void notifySmsStatus(Object result) { 1965 if (mSmsStatusRegistrant != null) { 1966 mSmsStatusRegistrant.notifyRegistrant(new AsyncResult(null, result, null)); 1967 } 1968 } 1969 1970 public void notifyGsmBroadcastSms(Object result) { 1971 if (mGsmBroadcastSmsRegistrant != null) { 1972 mGsmBroadcastSmsRegistrant.notifyRegistrant(new AsyncResult(null, result, null)); 1973 } 1974 } 1975 1976 public void notifyIccSmsFull() { 1977 if (mIccSmsFullRegistrant != null) { 1978 mIccSmsFullRegistrant.notifyRegistrant(); 1979 } 1980 } 1981 1982 public void notifyEmergencyCallbackMode() { 1983 if (mEmergencyCallbackModeRegistrant != null) { 1984 mEmergencyCallbackModeRegistrant.notifyRegistrant(); 1985 } 1986 } 1987 1988 @Override 1989 public void setEmergencyCallbackMode(Handler h, int what, Object obj) { 1990 SimulatedCommandsVerifier.getInstance().setEmergencyCallbackMode(h, what, obj); 1991 super.setEmergencyCallbackMode(h, what, obj); 1992 } 1993 1994 public void notifyExitEmergencyCallbackMode() { 1995 if (mExitEmergencyCallbackModeRegistrants != null) { 1996 mExitEmergencyCallbackModeRegistrants.notifyRegistrants( 1997 new AsyncResult (null, null, null)); 1998 } 1999 } 2000 2001 public void notifyImsNetworkStateChanged() { 2002 if(mImsNetworkStateChangedRegistrants != null) { 2003 mImsNetworkStateChangedRegistrants.notifyRegistrants(); 2004 } 2005 } 2006 2007 @Override 2008 public void registerForExitEmergencyCallbackMode(Handler h, int what, Object obj) { 2009 SimulatedCommandsVerifier.getInstance().registerForExitEmergencyCallbackMode(h, what, obj); 2010 super.registerForExitEmergencyCallbackMode(h, what, obj); 2011 } 2012 2013 public void notifyRadioOn() { 2014 mOnRegistrants.notifyRegistrants(); 2015 } 2016 2017 @VisibleForTesting 2018 public void notifyVoiceNetworkStateChanged() { 2019 mVoiceNetworkStateRegistrants.notifyRegistrants(); 2020 } 2021 2022 @VisibleForTesting 2023 public void notifyOtaProvisionStatusChanged() { 2024 if (mOtaProvisionRegistrants != null) { 2025 int ret[] = new int[1]; 2026 ret[0] = Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED; 2027 mOtaProvisionRegistrants.notifyRegistrants(new AsyncResult(null, ret, null)); 2028 } 2029 } 2030 2031 public void notifySignalStrength() { 2032 if (mSignalStrength == null) { 2033 mSignalStrength = new SignalStrength( 2034 20, // gsmSignalStrength 2035 0, // gsmBitErrorRate 2036 -1, // cdmaDbm 2037 -1, // cdmaEcio 2038 -1, // evdoDbm 2039 -1, // evdoEcio 2040 -1, // evdoSnr 2041 99, // lteSignalStrength 2042 SignalStrength.INVALID, // lteRsrp 2043 SignalStrength.INVALID, // lteRsrq 2044 SignalStrength.INVALID, // lteRssnr 2045 SignalStrength.INVALID, // lteCqi 2046 SignalStrength.INVALID, // tdScdmaRscp 2047 true // gsmFlag 2048 ); 2049 } 2050 2051 if (mSignalStrengthRegistrant != null) { 2052 mSignalStrengthRegistrant.notifyRegistrant( 2053 new AsyncResult (null, mSignalStrength, null)); 2054 } 2055 } 2056 2057 public void setIccCardStatus(IccCardStatus iccCardStatus){ 2058 mIccCardStatus = iccCardStatus; 2059 } 2060 2061 public void setIccIoResultForApduLogicalChannel(IccIoResult iccIoResult) { 2062 mIccIoResultForApduLogicalChannel = iccIoResult; 2063 } 2064 2065 public void setOpenChannelId(int channelId) { 2066 mChannelId = channelId; 2067 } 2068 2069 public void setPin1RemainingAttempt(int pin1attemptsRemaining) { 2070 mPin1attemptsRemaining = pin1attemptsRemaining; 2071 } 2072 2073 private AtomicBoolean mAllowed = new AtomicBoolean(false); 2074 2075 @Override 2076 public void setDataAllowed(boolean allowed, Message result) { 2077 log("setDataAllowed = " + allowed); 2078 mAllowed.set(allowed); 2079 resultSuccess(result, null); 2080 } 2081 2082 @VisibleForTesting 2083 public boolean isDataAllowed() { 2084 return mAllowed.get(); 2085 } 2086} 2087