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.HandlerThread; 21import android.os.Looper; 22import android.os.Message; 23import android.util.Log; 24 25import com.android.internal.telephony.BaseCommands; 26import com.android.internal.telephony.CommandException; 27import com.android.internal.telephony.CommandsInterface; 28import com.android.internal.telephony.DataCallState; 29import com.android.internal.telephony.Phone; 30import com.android.internal.telephony.UUSInfo; 31import com.android.internal.telephony.gsm.CallFailCause; 32import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; 33import com.android.internal.telephony.gsm.SuppServiceNotification; 34 35import java.util.ArrayList; 36 37public final class SimulatedCommands extends BaseCommands 38 implements CommandsInterface, SimulatedRadioControl { 39 private final static String LOG_TAG = "SIM"; 40 41 private enum SimLockState { 42 NONE, 43 REQUIRE_PIN, 44 REQUIRE_PUK, 45 SIM_PERM_LOCKED 46 } 47 48 private enum SimFdnState { 49 NONE, 50 REQUIRE_PIN2, 51 REQUIRE_PUK2, 52 SIM_PERM_LOCKED 53 } 54 55 private final static SimLockState INITIAL_LOCK_STATE = SimLockState.NONE; 56 private final static String DEFAULT_SIM_PIN_CODE = "1234"; 57 private final static String SIM_PUK_CODE = "12345678"; 58 private final static SimFdnState INITIAL_FDN_STATE = SimFdnState.NONE; 59 private final static String DEFAULT_SIM_PIN2_CODE = "5678"; 60 private final static String SIM_PUK2_CODE = "87654321"; 61 62 //***** Instance Variables 63 64 SimulatedGsmCallState simulatedCallState; 65 HandlerThread mHandlerThread; 66 SimLockState mSimLockedState; 67 boolean mSimLockEnabled; 68 int mPinUnlockAttempts; 69 int mPukUnlockAttempts; 70 String mPinCode; 71 SimFdnState mSimFdnEnabledState; 72 boolean mSimFdnEnabled; 73 int mPin2UnlockAttempts; 74 int mPuk2UnlockAttempts; 75 int mNetworkType; 76 String mPin2Code; 77 boolean mSsnNotifyOn = false; 78 79 int pausedResponseCount; 80 ArrayList<Message> pausedResponses = new ArrayList<Message>(); 81 82 int nextCallFailCause = CallFailCause.NORMAL_CLEARING; 83 84 //***** Constructor 85 86 public 87 SimulatedCommands() { 88 super(null); // Don't log statistics 89 mHandlerThread = new HandlerThread("SimulatedCommands"); 90 mHandlerThread.start(); 91 Looper looper = mHandlerThread.getLooper(); 92 93 simulatedCallState = new SimulatedGsmCallState(looper); 94 95 setRadioState(RadioState.RADIO_OFF); 96 mSimLockedState = INITIAL_LOCK_STATE; 97 mSimLockEnabled = (mSimLockedState != SimLockState.NONE); 98 mPinCode = DEFAULT_SIM_PIN_CODE; 99 mSimFdnEnabledState = INITIAL_FDN_STATE; 100 mSimFdnEnabled = (mSimFdnEnabledState != SimFdnState.NONE); 101 mPin2Code = DEFAULT_SIM_PIN2_CODE; 102 } 103 104 //***** CommandsInterface implementation 105 106 public void getIccCardStatus(Message result) { 107 unimplemented(result); 108 } 109 110 public void supplyIccPin(String pin, Message result) { 111 if (mSimLockedState != SimLockState.REQUIRE_PIN) { 112 Log.i(LOG_TAG, "[SimCmd] supplyIccPin: wrong state, state=" + 113 mSimLockedState); 114 CommandException ex = new CommandException( 115 CommandException.Error.PASSWORD_INCORRECT); 116 AsyncResult.forMessage(result, null, ex); 117 result.sendToTarget(); 118 return; 119 } 120 121 if (pin != null && pin.equals(mPinCode)) { 122 Log.i(LOG_TAG, "[SimCmd] supplyIccPin: success!"); 123 setRadioState(RadioState.SIM_READY); 124 mPinUnlockAttempts = 0; 125 mSimLockedState = SimLockState.NONE; 126 127 if (result != null) { 128 AsyncResult.forMessage(result, null, null); 129 result.sendToTarget(); 130 } 131 132 return; 133 } 134 135 if (result != null) { 136 mPinUnlockAttempts ++; 137 138 Log.i(LOG_TAG, "[SimCmd] supplyIccPin: failed! attempt=" + 139 mPinUnlockAttempts); 140 if (mPinUnlockAttempts >= 3) { 141 Log.i(LOG_TAG, "[SimCmd] supplyIccPin: set state to REQUIRE_PUK"); 142 mSimLockedState = SimLockState.REQUIRE_PUK; 143 } 144 145 CommandException ex = new CommandException( 146 CommandException.Error.PASSWORD_INCORRECT); 147 AsyncResult.forMessage(result, null, ex); 148 result.sendToTarget(); 149 } 150 } 151 152 public void supplyIccPuk(String puk, String newPin, Message result) { 153 if (mSimLockedState != SimLockState.REQUIRE_PUK) { 154 Log.i(LOG_TAG, "[SimCmd] supplyIccPuk: wrong state, state=" + 155 mSimLockedState); 156 CommandException ex = new CommandException( 157 CommandException.Error.PASSWORD_INCORRECT); 158 AsyncResult.forMessage(result, null, ex); 159 result.sendToTarget(); 160 return; 161 } 162 163 if (puk != null && puk.equals(SIM_PUK_CODE)) { 164 Log.i(LOG_TAG, "[SimCmd] supplyIccPuk: success!"); 165 setRadioState(RadioState.SIM_READY); 166 mSimLockedState = SimLockState.NONE; 167 mPukUnlockAttempts = 0; 168 169 if (result != null) { 170 AsyncResult.forMessage(result, null, null); 171 result.sendToTarget(); 172 } 173 174 return; 175 } 176 177 if (result != null) { 178 mPukUnlockAttempts ++; 179 180 Log.i(LOG_TAG, "[SimCmd] supplyIccPuk: failed! attempt=" + 181 mPukUnlockAttempts); 182 if (mPukUnlockAttempts >= 10) { 183 Log.i(LOG_TAG, "[SimCmd] supplyIccPuk: set state to SIM_PERM_LOCKED"); 184 mSimLockedState = SimLockState.SIM_PERM_LOCKED; 185 } 186 187 CommandException ex = new CommandException( 188 CommandException.Error.PASSWORD_INCORRECT); 189 AsyncResult.forMessage(result, null, ex); 190 result.sendToTarget(); 191 } 192 } 193 194 public void supplyIccPin2(String pin2, Message result) { 195 if (mSimFdnEnabledState != SimFdnState.REQUIRE_PIN2) { 196 Log.i(LOG_TAG, "[SimCmd] supplyIccPin2: wrong state, state=" + 197 mSimFdnEnabledState); 198 CommandException ex = new CommandException( 199 CommandException.Error.PASSWORD_INCORRECT); 200 AsyncResult.forMessage(result, null, ex); 201 result.sendToTarget(); 202 return; 203 } 204 205 if (pin2 != null && pin2.equals(mPin2Code)) { 206 Log.i(LOG_TAG, "[SimCmd] supplyIccPin2: success!"); 207 mPin2UnlockAttempts = 0; 208 mSimFdnEnabledState = SimFdnState.NONE; 209 210 if (result != null) { 211 AsyncResult.forMessage(result, null, null); 212 result.sendToTarget(); 213 } 214 215 return; 216 } 217 218 if (result != null) { 219 mPin2UnlockAttempts ++; 220 221 Log.i(LOG_TAG, "[SimCmd] supplyIccPin2: failed! attempt=" + 222 mPin2UnlockAttempts); 223 if (mPin2UnlockAttempts >= 3) { 224 Log.i(LOG_TAG, "[SimCmd] supplyIccPin2: set state to REQUIRE_PUK2"); 225 mSimFdnEnabledState = SimFdnState.REQUIRE_PUK2; 226 } 227 228 CommandException ex = new CommandException( 229 CommandException.Error.PASSWORD_INCORRECT); 230 AsyncResult.forMessage(result, null, ex); 231 result.sendToTarget(); 232 } 233 } 234 235 public void supplyIccPuk2(String puk2, String newPin2, Message result) { 236 if (mSimFdnEnabledState != SimFdnState.REQUIRE_PUK2) { 237 Log.i(LOG_TAG, "[SimCmd] supplyIccPuk2: wrong state, state=" + 238 mSimLockedState); 239 CommandException ex = new CommandException( 240 CommandException.Error.PASSWORD_INCORRECT); 241 AsyncResult.forMessage(result, null, ex); 242 result.sendToTarget(); 243 return; 244 } 245 246 if (puk2 != null && puk2.equals(SIM_PUK2_CODE)) { 247 Log.i(LOG_TAG, "[SimCmd] supplyIccPuk2: success!"); 248 mSimFdnEnabledState = SimFdnState.NONE; 249 mPuk2UnlockAttempts = 0; 250 251 if (result != null) { 252 AsyncResult.forMessage(result, null, null); 253 result.sendToTarget(); 254 } 255 256 return; 257 } 258 259 if (result != null) { 260 mPuk2UnlockAttempts ++; 261 262 Log.i(LOG_TAG, "[SimCmd] supplyIccPuk2: failed! attempt=" + 263 mPuk2UnlockAttempts); 264 if (mPuk2UnlockAttempts >= 10) { 265 Log.i(LOG_TAG, "[SimCmd] supplyIccPuk2: set state to SIM_PERM_LOCKED"); 266 mSimFdnEnabledState = SimFdnState.SIM_PERM_LOCKED; 267 } 268 269 CommandException ex = new CommandException( 270 CommandException.Error.PASSWORD_INCORRECT); 271 AsyncResult.forMessage(result, null, ex); 272 result.sendToTarget(); 273 } 274 } 275 276 public void changeIccPin(String oldPin, String newPin, Message result) { 277 if (oldPin != null && oldPin.equals(mPinCode)) { 278 mPinCode = newPin; 279 if (result != null) { 280 AsyncResult.forMessage(result, null, null); 281 result.sendToTarget(); 282 } 283 284 return; 285 } 286 287 if (result != null) { 288 Log.i(LOG_TAG, "[SimCmd] changeIccPin: pin failed!"); 289 290 CommandException ex = new CommandException( 291 CommandException.Error.PASSWORD_INCORRECT); 292 AsyncResult.forMessage(result, null, ex); 293 result.sendToTarget(); 294 } 295 } 296 297 public void changeIccPin2(String oldPin2, String newPin2, Message result) { 298 if (oldPin2 != null && oldPin2.equals(mPin2Code)) { 299 mPin2Code = newPin2; 300 if (result != null) { 301 AsyncResult.forMessage(result, null, null); 302 result.sendToTarget(); 303 } 304 305 return; 306 } 307 308 if (result != null) { 309 Log.i(LOG_TAG, "[SimCmd] changeIccPin2: pin2 failed!"); 310 311 CommandException ex = new CommandException( 312 CommandException.Error.PASSWORD_INCORRECT); 313 AsyncResult.forMessage(result, null, ex); 314 result.sendToTarget(); 315 } 316 } 317 318 public void 319 changeBarringPassword(String facility, String oldPwd, String newPwd, Message result) { 320 unimplemented(result); 321 } 322 323 public void 324 setSuppServiceNotifications(boolean enable, Message result) { 325 resultSuccess(result, null); 326 327 if (enable && mSsnNotifyOn) { 328 Log.w(LOG_TAG, "Supp Service Notifications already enabled!"); 329 } 330 331 mSsnNotifyOn = enable; 332 } 333 334 @Override 335 public void queryFacilityLock(String facility, String pin, 336 int serviceClass, Message result) { 337 queryFacilityLockForApp(facility, pin, serviceClass, null, result); 338 } 339 340 @Override 341 public void queryFacilityLockForApp(String facility, String pin, int serviceClass, 342 String appId, Message result) { 343 if (facility != null && facility.equals(CommandsInterface.CB_FACILITY_BA_SIM)) { 344 if (result != null) { 345 int[] r = new int[1]; 346 r[0] = (mSimLockEnabled ? 1 : 0); 347 Log.i(LOG_TAG, "[SimCmd] queryFacilityLock: SIM is " 348 + (r[0] == 0 ? "unlocked" : "locked")); 349 AsyncResult.forMessage(result, r, null); 350 result.sendToTarget(); 351 } 352 return; 353 } else if (facility != null && facility.equals(CommandsInterface.CB_FACILITY_BA_FD)) { 354 if (result != null) { 355 int[] r = new int[1]; 356 r[0] = (mSimFdnEnabled ? 1 : 0); 357 Log.i(LOG_TAG, "[SimCmd] queryFacilityLock: FDN is " 358 + (r[0] == 0 ? "disabled" : "enabled")); 359 AsyncResult.forMessage(result, r, null); 360 result.sendToTarget(); 361 } 362 return; 363 } 364 365 unimplemented(result); 366 } 367 368 @Override 369 public void setFacilityLock(String facility, boolean lockEnabled, String pin, int serviceClass, 370 Message result) { 371 setFacilityLockForApp(facility, lockEnabled, pin, serviceClass, null, result); 372 } 373 374 @Override 375 public void setFacilityLockForApp(String facility, boolean lockEnabled, 376 String pin, int serviceClass, String appId, 377 Message result) { 378 if (facility != null && 379 facility.equals(CommandsInterface.CB_FACILITY_BA_SIM)) { 380 if (pin != null && pin.equals(mPinCode)) { 381 Log.i(LOG_TAG, "[SimCmd] setFacilityLock: pin is valid"); 382 mSimLockEnabled = lockEnabled; 383 384 if (result != null) { 385 AsyncResult.forMessage(result, null, null); 386 result.sendToTarget(); 387 } 388 389 return; 390 } 391 392 if (result != null) { 393 Log.i(LOG_TAG, "[SimCmd] setFacilityLock: pin failed!"); 394 395 CommandException ex = new CommandException( 396 CommandException.Error.GENERIC_FAILURE); 397 AsyncResult.forMessage(result, null, ex); 398 result.sendToTarget(); 399 } 400 401 return; 402 } else if (facility != null && 403 facility.equals(CommandsInterface.CB_FACILITY_BA_FD)) { 404 if (pin != null && pin.equals(mPin2Code)) { 405 Log.i(LOG_TAG, "[SimCmd] setFacilityLock: pin2 is valid"); 406 mSimFdnEnabled = lockEnabled; 407 408 if (result != null) { 409 AsyncResult.forMessage(result, null, null); 410 result.sendToTarget(); 411 } 412 413 return; 414 } 415 416 if (result != null) { 417 Log.i(LOG_TAG, "[SimCmd] setFacilityLock: pin2 failed!"); 418 419 CommandException ex = new CommandException( 420 CommandException.Error.GENERIC_FAILURE); 421 AsyncResult.forMessage(result, null, ex); 422 result.sendToTarget(); 423 } 424 425 return; 426 } 427 428 unimplemented(result); 429 } 430 431 public void supplyNetworkDepersonalization(String netpin, Message result) { 432 unimplemented(result); 433 } 434 435 /** 436 * returned message 437 * retMsg.obj = AsyncResult ar 438 * ar.exception carries exception on failure 439 * ar.userObject contains the original value of result.obj 440 * ar.result contains a List of DriverCall 441 * The ar.result List is sorted by DriverCall.index 442 */ 443 public void getCurrentCalls (Message result) { 444 if (mState == RadioState.SIM_READY) { 445 //Log.i("GSM", "[SimCmds] getCurrentCalls"); 446 resultSuccess(result, simulatedCallState.getDriverCalls()); 447 } else { 448 //Log.i("GSM", "[SimCmds] getCurrentCalls: SIM not ready!"); 449 resultFail(result, 450 new CommandException( 451 CommandException.Error.RADIO_NOT_AVAILABLE)); 452 } 453 } 454 455 /** 456 * @deprecated 457 */ 458 public void getPDPContextList(Message result) { 459 getDataCallList(result); 460 } 461 462 /** 463 * returned message 464 * retMsg.obj = AsyncResult ar 465 * ar.exception carries exception on failure 466 * ar.userObject contains the original value of result.obj 467 * ar.result contains a List of DataCallState 468 */ 469 public void getDataCallList(Message result) { 470 resultSuccess(result, new ArrayList<DataCallState>(0)); 471 } 472 473 /** 474 * returned message 475 * retMsg.obj = AsyncResult ar 476 * ar.exception carries exception on failure 477 * ar.userObject contains the original value of result.obj 478 * ar.result is null on success and failure 479 * 480 * CLIR_DEFAULT == on "use subscription default value" 481 * CLIR_SUPPRESSION == on "CLIR suppression" (allow CLI presentation) 482 * CLIR_INVOCATION == on "CLIR invocation" (restrict CLI presentation) 483 */ 484 public void dial (String address, int clirMode, Message result) { 485 simulatedCallState.onDial(address); 486 487 resultSuccess(result, null); 488 } 489 490 /** 491 * returned message 492 * retMsg.obj = AsyncResult ar 493 * ar.exception carries exception on failure 494 * ar.userObject contains the original value of result.obj 495 * ar.result is null on success and failure 496 * 497 * CLIR_DEFAULT == on "use subscription default value" 498 * CLIR_SUPPRESSION == on "CLIR suppression" (allow CLI presentation) 499 * CLIR_INVOCATION == on "CLIR invocation" (restrict CLI presentation) 500 */ 501 public void dial(String address, int clirMode, UUSInfo uusInfo, Message result) { 502 simulatedCallState.onDial(address); 503 504 resultSuccess(result, null); 505 } 506 507 /** 508 * returned message 509 * retMsg.obj = AsyncResult ar 510 * ar.exception carries exception on failure 511 * ar.userObject contains the original value of result.obj 512 * ar.result is String containing IMSI on success 513 */ 514 public void getIMSI(Message result) { 515 resultSuccess(result, "012345678901234"); 516 } 517 518 /** 519 * returned message 520 * retMsg.obj = AsyncResult ar 521 * ar.exception carries exception on failure 522 * ar.userObject contains the original value of result.obj 523 * ar.result is String containing IMEI on success 524 */ 525 public void getIMEI(Message result) { 526 resultSuccess(result, "012345678901234"); 527 } 528 529 /** 530 * returned message 531 * retMsg.obj = AsyncResult ar 532 * ar.exception carries exception on failure 533 * ar.userObject contains the original value of result.obj 534 * ar.result is String containing IMEISV on success 535 */ 536 public void getIMEISV(Message result) { 537 resultSuccess(result, "99"); 538 } 539 540 /** 541 * Hang up one individual connection. 542 * returned message 543 * retMsg.obj = AsyncResult ar 544 * ar.exception carries exception on failure 545 * ar.userObject contains the original value of result.obj 546 * ar.result is null on success and failure 547 * 548 * 3GPP 22.030 6.5.5 549 * "Releases a specific active call X" 550 */ 551 public void hangupConnection (int gsmIndex, Message result) { 552 boolean success; 553 554 success = simulatedCallState.onChld('1', (char)('0'+gsmIndex)); 555 556 if (!success){ 557 Log.i("GSM", "[SimCmd] hangupConnection: resultFail"); 558 resultFail(result, new RuntimeException("Hangup Error")); 559 } else { 560 Log.i("GSM", "[SimCmd] hangupConnection: resultSuccess"); 561 resultSuccess(result, null); 562 } 563 } 564 565 /** 566 * 3GPP 22.030 6.5.5 567 * "Releases all held calls or sets User Determined User Busy (UDUB) 568 * for a waiting call." 569 * ar.exception carries exception on failure 570 * ar.userObject contains the original value of result.obj 571 * ar.result is null on success and failure 572 */ 573 public void hangupWaitingOrBackground (Message result) { 574 boolean success; 575 576 success = simulatedCallState.onChld('0', '\0'); 577 578 if (!success){ 579 resultFail(result, new RuntimeException("Hangup Error")); 580 } else { 581 resultSuccess(result, null); 582 } 583 } 584 585 /** 586 * 3GPP 22.030 6.5.5 587 * "Releases all active calls (if any exist) and accepts 588 * the other (held or waiting) call." 589 * 590 * ar.exception carries exception on failure 591 * ar.userObject contains the original value of result.obj 592 * ar.result is null on success and failure 593 */ 594 public void hangupForegroundResumeBackground (Message result) { 595 boolean success; 596 597 success = simulatedCallState.onChld('1', '\0'); 598 599 if (!success){ 600 resultFail(result, new RuntimeException("Hangup Error")); 601 } else { 602 resultSuccess(result, null); 603 } 604 } 605 606 /** 607 * 3GPP 22.030 6.5.5 608 * "Places all active calls (if any exist) on hold and accepts 609 * the other (held or waiting) call." 610 * 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 public void switchWaitingOrHoldingAndActive (Message result) { 616 boolean success; 617 618 success = simulatedCallState.onChld('2', '\0'); 619 620 if (!success){ 621 resultFail(result, new RuntimeException("Hangup Error")); 622 } else { 623 resultSuccess(result, null); 624 } 625 } 626 627 /** 628 * 3GPP 22.030 6.5.5 629 * "Adds a held call to the conversation" 630 * 631 * ar.exception carries exception on failure 632 * ar.userObject contains the original value of result.obj 633 * ar.result is null on success and failure 634 */ 635 public void conference (Message result) { 636 boolean success; 637 638 success = simulatedCallState.onChld('3', '\0'); 639 640 if (!success){ 641 resultFail(result, new RuntimeException("Hangup Error")); 642 } else { 643 resultSuccess(result, null); 644 } 645 } 646 647 /** 648 * 3GPP 22.030 6.5.5 649 * "Connects the two calls and disconnects the subscriber from both calls" 650 * 651 * ar.exception carries exception on failure 652 * ar.userObject contains the original value of result.obj 653 * ar.result is null on success and failure 654 */ 655 public void explicitCallTransfer (Message result) { 656 boolean success; 657 658 success = simulatedCallState.onChld('4', '\0'); 659 660 if (!success){ 661 resultFail(result, new RuntimeException("Hangup Error")); 662 } else { 663 resultSuccess(result, null); 664 } 665 } 666 667 /** 668 * 3GPP 22.030 6.5.5 669 * "Places all active calls on hold except call X with which 670 * communication shall be supported." 671 */ 672 public void separateConnection (int gsmIndex, Message result) { 673 boolean success; 674 675 char ch = (char)(gsmIndex + '0'); 676 success = simulatedCallState.onChld('2', ch); 677 678 if (!success){ 679 resultFail(result, new RuntimeException("Hangup Error")); 680 } else { 681 resultSuccess(result, null); 682 } 683 } 684 685 /** 686 * 687 * ar.exception carries exception on failure 688 * ar.userObject contains the original value of result.obj 689 * ar.result is null on success and failure 690 */ 691 public void acceptCall (Message result) { 692 boolean success; 693 694 success = simulatedCallState.onAnswer(); 695 696 if (!success){ 697 resultFail(result, new RuntimeException("Hangup Error")); 698 } else { 699 resultSuccess(result, null); 700 } 701 } 702 703 /** 704 * also known as UDUB 705 * ar.exception carries exception on failure 706 * ar.userObject contains the original value of result.obj 707 * ar.result is null on success and failure 708 */ 709 public void rejectCall (Message result) { 710 boolean success; 711 712 success = simulatedCallState.onChld('0', '\0'); 713 714 if (!success){ 715 resultFail(result, new RuntimeException("Hangup Error")); 716 } else { 717 resultSuccess(result, null); 718 } 719 } 720 721 /** 722 * cause code returned as Integer in Message.obj.response 723 * Returns integer cause code defined in TS 24.008 724 * Annex H or closest approximation. 725 * Most significant codes: 726 * - Any defined in 22.001 F.4 (for generating busy/congestion) 727 * - Cause 68: ACM >= ACMMax 728 */ 729 public void getLastCallFailCause (Message result) { 730 int[] ret = new int[1]; 731 732 ret[0] = nextCallFailCause; 733 resultSuccess(result, ret); 734 } 735 736 /** 737 * @deprecated 738 */ 739 public void getLastPdpFailCause (Message result) { 740 unimplemented(result); 741 } 742 743 public void getLastDataCallFailCause(Message result) { 744 // 745 unimplemented(result); 746 } 747 748 public void setMute (boolean enableMute, Message result) {unimplemented(result);} 749 750 public void getMute (Message result) {unimplemented(result);} 751 752 /** 753 * response.obj is an AsyncResult 754 * response.obj.result is an int[2] 755 * response.obj.result[0] is received signal strength (0-31, 99) 756 * response.obj.result[1] is bit error rate (0-7, 99) 757 * as defined in TS 27.007 8.5 758 */ 759 public void getSignalStrength (Message result) { 760 int ret[] = new int[2]; 761 762 ret[0] = 23; 763 ret[1] = 0; 764 765 resultSuccess(result, ret); 766 } 767 768 /** 769 * Assign a specified band for RF configuration. 770 * 771 * @param bandMode one of BM_*_BAND 772 * @param result is callback message 773 */ 774 public void setBandMode (int bandMode, Message result) { 775 resultSuccess(result, null); 776 } 777 778 /** 779 * Query the list of band mode supported by RF. 780 * 781 * @param result is callback message 782 * ((AsyncResult)response.obj).result is an int[] with every 783 * element representing one available BM_*_BAND 784 */ 785 public void queryAvailableBandMode (Message result) { 786 int ret[] = new int [4]; 787 788 ret[0] = 4; 789 ret[1] = Phone.BM_US_BAND; 790 ret[2] = Phone.BM_JPN_BAND; 791 ret[3] = Phone.BM_AUS_BAND; 792 793 resultSuccess(result, ret); 794 } 795 796 /** 797 * {@inheritDoc} 798 */ 799 public void sendTerminalResponse(String contents, Message response) { 800 resultSuccess(response, null); 801 } 802 803 /** 804 * {@inheritDoc} 805 */ 806 public void sendEnvelope(String contents, Message response) { 807 resultSuccess(response, null); 808 } 809 810 /** 811 * {@inheritDoc} 812 */ 813 public void sendEnvelopeWithStatus(String contents, Message response) { 814 resultSuccess(response, null); 815 } 816 817 /** 818 * {@inheritDoc} 819 */ 820 public void handleCallSetupRequestFromSim( 821 boolean accept, Message response) { 822 resultSuccess(response, null); 823 } 824 825 /** 826 * response.obj.result is an String[14] 827 * See ril.h for details 828 * 829 * Please note that registration state 4 ("unknown") is treated 830 * as "out of service" above 831 */ 832 public void getVoiceRegistrationState (Message result) { 833 String ret[] = new String[14]; 834 835 ret[0] = "5"; // registered roam 836 ret[1] = null; 837 ret[2] = null; 838 ret[3] = null; 839 ret[4] = null; 840 ret[5] = null; 841 ret[6] = null; 842 ret[7] = null; 843 ret[8] = null; 844 ret[9] = null; 845 ret[10] = null; 846 ret[11] = null; 847 ret[12] = null; 848 ret[13] = null; 849 850 resultSuccess(result, ret); 851 } 852 853 /** 854 * response.obj.result is an String[4] 855 * response.obj.result[0] is registration state 0-5 from TS 27.007 7.2 856 * response.obj.result[1] is LAC if registered or NULL if not 857 * response.obj.result[2] is CID if registered or NULL if not 858 * response.obj.result[3] indicates the available radio technology, where: 859 * 0 == unknown 860 * 1 == GPRS only 861 * 2 == EDGE 862 * 3 == UMTS 863 * 864 * valid LAC are 0x0000 - 0xffff 865 * valid CID are 0x00000000 - 0xffffffff 866 * 867 * Please note that registration state 4 ("unknown") is treated 868 * as "out of service" in the Android telephony system 869 */ 870 public void getDataRegistrationState (Message result) { 871 String ret[] = new String[4]; 872 873 ret[0] = "5"; // registered roam 874 ret[1] = null; 875 ret[2] = null; 876 ret[3] = "2"; 877 878 resultSuccess(result, ret); 879 } 880 881 /** 882 * response.obj.result is a String[3] 883 * response.obj.result[0] is long alpha or null if unregistered 884 * response.obj.result[1] is short alpha or null if unregistered 885 * response.obj.result[2] is numeric or null if unregistered 886 */ 887 public void getOperator(Message result) { 888 String[] ret = new String[3]; 889 890 ret[0] = "El Telco Loco"; 891 ret[1] = "Telco Loco"; 892 ret[2] = "001001"; 893 894 resultSuccess(result, ret); 895 } 896 897 /** 898 * ar.exception carries exception on failure 899 * ar.userObject contains the original value of result.obj 900 * ar.result is null on success and failure 901 */ 902 public void sendDtmf(char c, Message result) { 903 resultSuccess(result, null); 904 } 905 906 /** 907 * ar.exception carries exception on failure 908 * ar.userObject contains the original value of result.obj 909 * ar.result is null on success and failure 910 */ 911 public void startDtmf(char c, Message result) { 912 resultSuccess(result, null); 913 } 914 915 /** 916 * ar.exception carries exception on failure 917 * ar.userObject contains the original value of result.obj 918 * ar.result is null on success and failure 919 */ 920 public void stopDtmf(Message result) { 921 resultSuccess(result, null); 922 } 923 924 /** 925 * ar.exception carries exception on failure 926 * ar.userObject contains the original value of result.obj 927 * ar.result is null on success and failure 928 */ 929 public void sendBurstDtmf(String dtmfString, int on, int off, Message result) { 930 resultSuccess(result, null); 931 } 932 933 /** 934 * smscPDU is smsc address in PDU form GSM BCD format prefixed 935 * by a length byte (as expected by TS 27.005) or NULL for default SMSC 936 * pdu is SMS in PDU format as an ASCII hex string 937 * less the SMSC address 938 */ 939 public void sendSMS (String smscPDU, String pdu, Message result) {unimplemented(result);} 940 941 public void deleteSmsOnSim(int index, Message response) { 942 Log.d(LOG_TAG, "Delete message at index " + index); 943 unimplemented(response); 944 } 945 946 public void deleteSmsOnRuim(int index, Message response) { 947 Log.d(LOG_TAG, "Delete RUIM message at index " + index); 948 unimplemented(response); 949 } 950 951 public void writeSmsToSim(int status, String smsc, String pdu, Message response) { 952 Log.d(LOG_TAG, "Write SMS to SIM with status " + status); 953 unimplemented(response); 954 } 955 956 public void writeSmsToRuim(int status, String pdu, Message response) { 957 Log.d(LOG_TAG, "Write SMS to RUIM with status " + status); 958 unimplemented(response); 959 } 960 961 public void setupDataCall(String radioTechnology, String profile, 962 String apn, String user, String password, String authType, 963 String protocol, Message result) { 964 unimplemented(result); 965 } 966 967 public void deactivateDataCall(int cid, int reason, Message result) {unimplemented(result);} 968 969 public void setPreferredNetworkType(int networkType , Message result) { 970 mNetworkType = networkType; 971 resultSuccess(result, null); 972 } 973 974 public void getPreferredNetworkType(Message result) { 975 int ret[] = new int[1]; 976 977 ret[0] = mNetworkType; 978 resultSuccess(result, ret); 979 } 980 981 public void getNeighboringCids(Message result) { 982 int ret[] = new int[7]; 983 984 ret[0] = 6; 985 for (int i = 1; i<7; i++) { 986 ret[i] = i; 987 } 988 resultSuccess(result, ret); 989 } 990 991 public void setLocationUpdates(boolean enable, Message response) { 992 unimplemented(response); 993 } 994 995 public void getSmscAddress(Message result) { 996 unimplemented(result); 997 } 998 999 public void setSmscAddress(String address, Message result) { 1000 unimplemented(result); 1001 } 1002 1003 public void reportSmsMemoryStatus(boolean available, Message result) { 1004 unimplemented(result); 1005 } 1006 1007 public void reportStkServiceIsRunning(Message result) { 1008 resultSuccess(result, null); 1009 } 1010 1011 @Override 1012 public void getCdmaSubscriptionSource(Message result) { 1013 unimplemented(result); 1014 } 1015 1016 private boolean isSimLocked() { 1017 if (mSimLockedState != SimLockState.NONE) { 1018 return true; 1019 } 1020 return false; 1021 } 1022 1023 public void setRadioPower(boolean on, Message result) { 1024 if(on) { 1025 if (isSimLocked()) { 1026 Log.i("SIM", "[SimCmd] setRadioPower: SIM locked! state=" + 1027 mSimLockedState); 1028 setRadioState(RadioState.SIM_LOCKED_OR_ABSENT); 1029 } 1030 else { 1031 setRadioState(RadioState.SIM_READY); 1032 } 1033 } else { 1034 setRadioState(RadioState.RADIO_OFF); 1035 } 1036 } 1037 1038 1039 public void acknowledgeLastIncomingGsmSms(boolean success, int cause, Message result) { 1040 unimplemented(result); 1041 } 1042 1043 public void acknowledgeLastIncomingCdmaSms(boolean success, int cause, Message result) { 1044 unimplemented(result); 1045 } 1046 1047 public void acknowledgeIncomingGsmSmsWithPdu(boolean success, String ackPdu, 1048 Message result) { 1049 unimplemented(result); 1050 } 1051 1052 /** 1053 * parameters equivalent to 27.007 AT+CRSM command 1054 * response.obj will be an AsyncResult 1055 * response.obj.userObj will be a SimIoResult on success 1056 */ 1057 public void iccIO (int command, int fileid, String path, int p1, int p2, 1058 int p3, String data, String pin2, Message result) { 1059 unimplemented(result); 1060 } 1061 1062 /** 1063 * (AsyncResult)response.obj).result is an int[] with element [0] set to 1064 * 1 for "CLIP is provisioned", and 0 for "CLIP is not provisioned". 1065 * 1066 * @param response is callback message 1067 */ 1068 public void queryCLIP(Message response) { unimplemented(response); } 1069 1070 1071 /** 1072 * response.obj will be a an int[2] 1073 * 1074 * response.obj[0] will be TS 27.007 +CLIR parameter 'n' 1075 * 0 presentation indicator is used according to the subscription of the CLIR service 1076 * 1 CLIR invocation 1077 * 2 CLIR suppression 1078 * 1079 * response.obj[1] will be TS 27.007 +CLIR parameter 'm' 1080 * 0 CLIR not provisioned 1081 * 1 CLIR provisioned in permanent mode 1082 * 2 unknown (e.g. no network, etc.) 1083 * 3 CLIR temporary mode presentation restricted 1084 * 4 CLIR temporary mode presentation allowed 1085 */ 1086 1087 public void getCLIR(Message result) {unimplemented(result);} 1088 1089 /** 1090 * clirMode is one of the CLIR_* constants above 1091 * 1092 * response.obj is null 1093 */ 1094 1095 public void setCLIR(int clirMode, Message result) {unimplemented(result);} 1096 1097 /** 1098 * (AsyncResult)response.obj).result is an int[] with element [0] set to 1099 * 0 for disabled, 1 for enabled. 1100 * 1101 * @param serviceClass is a sum of SERVICE_CLASS_* 1102 * @param response is callback message 1103 */ 1104 1105 public void queryCallWaiting(int serviceClass, Message response) { 1106 unimplemented(response); 1107 } 1108 1109 /** 1110 * @param enable is true to enable, false to disable 1111 * @param serviceClass is a sum of SERVICE_CLASS_* 1112 * @param response is callback message 1113 */ 1114 1115 public void setCallWaiting(boolean enable, int serviceClass, 1116 Message response) { 1117 unimplemented(response); 1118 } 1119 1120 /** 1121 * @param action is one of CF_ACTION_* 1122 * @param cfReason is one of CF_REASON_* 1123 * @param serviceClass is a sum of SERVICE_CLASSS_* 1124 */ 1125 public void setCallForward(int action, int cfReason, int serviceClass, 1126 String number, int timeSeconds, Message result) {unimplemented(result);} 1127 1128 /** 1129 * cfReason is one of CF_REASON_* 1130 * 1131 * ((AsyncResult)response.obj).result will be an array of 1132 * CallForwardInfo's 1133 * 1134 * An array of length 0 means "disabled for all codes" 1135 */ 1136 public void queryCallForwardStatus(int cfReason, int serviceClass, 1137 String number, Message result) {unimplemented(result);} 1138 1139 public void setNetworkSelectionModeAutomatic(Message result) {unimplemented(result);} 1140 public void exitEmergencyCallbackMode(Message result) {unimplemented(result);} 1141 public void setNetworkSelectionModeManual( 1142 String operatorNumeric, Message result) {unimplemented(result);} 1143 1144 /** 1145 * Queries whether the current network selection mode is automatic 1146 * or manual 1147 * 1148 * ((AsyncResult)response.obj).result is an int[] with element [0] being 1149 * a 0 for automatic selection and a 1 for manual selection 1150 */ 1151 1152 public void getNetworkSelectionMode(Message result) { 1153 int ret[] = new int[1]; 1154 1155 ret[0] = 0; 1156 resultSuccess(result, ret); 1157 } 1158 1159 /** 1160 * Queries the currently available networks 1161 * 1162 * ((AsyncResult)response.obj).result is a List of NetworkInfo objects 1163 */ 1164 public void getAvailableNetworks(Message result) {unimplemented(result);} 1165 1166 public void getBasebandVersion (Message result) { 1167 resultSuccess(result, "SimulatedCommands"); 1168 } 1169 1170 /** 1171 * Simulates an incoming USSD message 1172 * @param statusCode Status code string. See <code>setOnUSSD</code> 1173 * in CommandsInterface.java 1174 * @param message Message text to send or null if none 1175 */ 1176 public void triggerIncomingUssd(String statusCode, String message) { 1177 if (mUSSDRegistrant != null) { 1178 String[] result = {statusCode, message}; 1179 mUSSDRegistrant.notifyResult(result); 1180 } 1181 } 1182 1183 1184 public void sendUSSD (String ussdString, Message result) { 1185 1186 // We simulate this particular sequence 1187 if (ussdString.equals("#646#")) { 1188 resultSuccess(result, null); 1189 1190 // 0 == USSD-Notify 1191 triggerIncomingUssd("0", "You have NNN minutes remaining."); 1192 } else { 1193 resultSuccess(result, null); 1194 1195 triggerIncomingUssd("0", "All Done"); 1196 } 1197 } 1198 1199 // inherited javadoc suffices 1200 public void cancelPendingUssd (Message response) { 1201 resultSuccess(response, null); 1202 } 1203 1204 1205 public void resetRadio(Message result) { 1206 unimplemented(result); 1207 } 1208 1209 public void invokeOemRilRequestRaw(byte[] data, Message response) { 1210 // Just echo back data 1211 if (response != null) { 1212 AsyncResult.forMessage(response).result = data; 1213 response.sendToTarget(); 1214 } 1215 } 1216 1217 public void invokeOemRilRequestStrings(String[] strings, Message response) { 1218 // Just echo back data 1219 if (response != null) { 1220 AsyncResult.forMessage(response).result = strings; 1221 response.sendToTarget(); 1222 } 1223 } 1224 1225 //***** SimulatedRadioControl 1226 1227 1228 /** Start the simulated phone ringing */ 1229 public void 1230 triggerRing(String number) { 1231 simulatedCallState.triggerRing(number); 1232 mCallStateRegistrants.notifyRegistrants(); 1233 } 1234 1235 public void 1236 progressConnectingCallState() { 1237 simulatedCallState.progressConnectingCallState(); 1238 mCallStateRegistrants.notifyRegistrants(); 1239 } 1240 1241 /** If a call is DIALING or ALERTING, progress it all the way to ACTIVE */ 1242 public void 1243 progressConnectingToActive() { 1244 simulatedCallState.progressConnectingToActive(); 1245 mCallStateRegistrants.notifyRegistrants(); 1246 } 1247 1248 /** automatically progress mobile originated calls to ACTIVE. 1249 * default to true 1250 */ 1251 public void 1252 setAutoProgressConnectingCall(boolean b) { 1253 simulatedCallState.setAutoProgressConnectingCall(b); 1254 } 1255 1256 public void 1257 setNextDialFailImmediately(boolean b) { 1258 simulatedCallState.setNextDialFailImmediately(b); 1259 } 1260 1261 public void 1262 setNextCallFailCause(int gsmCause) { 1263 nextCallFailCause = gsmCause; 1264 } 1265 1266 public void 1267 triggerHangupForeground() { 1268 simulatedCallState.triggerHangupForeground(); 1269 mCallStateRegistrants.notifyRegistrants(); 1270 } 1271 1272 /** hangup holding calls */ 1273 public void 1274 triggerHangupBackground() { 1275 simulatedCallState.triggerHangupBackground(); 1276 mCallStateRegistrants.notifyRegistrants(); 1277 } 1278 1279 public void triggerSsn(int type, int code) { 1280 SuppServiceNotification not = new SuppServiceNotification(); 1281 not.notificationType = type; 1282 not.code = code; 1283 mSsnRegistrant.notifyRegistrant(new AsyncResult(null, not, null)); 1284 } 1285 1286 public void 1287 shutdown() { 1288 setRadioState(RadioState.RADIO_UNAVAILABLE); 1289 Looper looper = mHandlerThread.getLooper(); 1290 if (looper != null) { 1291 looper.quit(); 1292 } 1293 } 1294 1295 /** hangup all */ 1296 1297 public void 1298 triggerHangupAll() { 1299 simulatedCallState.triggerHangupAll(); 1300 mCallStateRegistrants.notifyRegistrants(); 1301 } 1302 1303 public void 1304 triggerIncomingSMS(String message) { 1305 //TODO 1306 } 1307 1308 public void 1309 pauseResponses() { 1310 pausedResponseCount++; 1311 } 1312 1313 public void 1314 resumeResponses() { 1315 pausedResponseCount--; 1316 1317 if (pausedResponseCount == 0) { 1318 for (int i = 0, s = pausedResponses.size(); i < s ; i++) { 1319 pausedResponses.get(i).sendToTarget(); 1320 } 1321 pausedResponses.clear(); 1322 } else { 1323 Log.e("GSM", "SimulatedCommands.resumeResponses < 0"); 1324 } 1325 } 1326 1327 //***** Private Methods 1328 1329 private void unimplemented(Message result) { 1330 if (result != null) { 1331 AsyncResult.forMessage(result).exception 1332 = new RuntimeException("Unimplemented"); 1333 1334 if (pausedResponseCount > 0) { 1335 pausedResponses.add(result); 1336 } else { 1337 result.sendToTarget(); 1338 } 1339 } 1340 } 1341 1342 private void resultSuccess(Message result, Object ret) { 1343 if (result != null) { 1344 AsyncResult.forMessage(result).result = ret; 1345 if (pausedResponseCount > 0) { 1346 pausedResponses.add(result); 1347 } else { 1348 result.sendToTarget(); 1349 } 1350 } 1351 } 1352 1353 private void resultFail(Message result, Throwable tr) { 1354 if (result != null) { 1355 AsyncResult.forMessage(result).exception = tr; 1356 if (pausedResponseCount > 0) { 1357 pausedResponses.add(result); 1358 } else { 1359 result.sendToTarget(); 1360 } 1361 } 1362 } 1363 1364 // ***** Methods for CDMA support 1365 public void 1366 getDeviceIdentity(Message response) { 1367 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1368 unimplemented(response); 1369 } 1370 1371 public void 1372 getCDMASubscription(Message response) { 1373 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1374 unimplemented(response); 1375 } 1376 1377 public void 1378 setCdmaSubscriptionSource(int cdmaSubscriptionType, Message response) { 1379 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1380 unimplemented(response); 1381 } 1382 1383 public void queryCdmaRoamingPreference(Message response) { 1384 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1385 unimplemented(response); 1386 } 1387 1388 public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) { 1389 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1390 unimplemented(response); 1391 } 1392 1393 public void 1394 setPhoneType(int phoneType) { 1395 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1396 } 1397 1398 public void getPreferredVoicePrivacy(Message result) { 1399 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1400 unimplemented(result); 1401 } 1402 1403 public void setPreferredVoicePrivacy(boolean enable, Message result) { 1404 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1405 unimplemented(result); 1406 } 1407 1408 /** 1409 * Set the TTY mode 1410 * 1411 * @param ttyMode is one of the following: 1412 * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} 1413 * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} 1414 * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} 1415 * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO} 1416 * @param response is callback message 1417 */ 1418 public void setTTYMode(int ttyMode, Message response) { 1419 Log.w(LOG_TAG, "Not implemented in SimulatedCommands"); 1420 unimplemented(response); 1421 } 1422 1423 /** 1424 * Query the TTY mode 1425 * (AsyncResult)response.obj).result is an int[] with element [0] set to 1426 * tty mode: 1427 * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} 1428 * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} 1429 * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} 1430 * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO} 1431 * @param response is callback message 1432 */ 1433 public void queryTTYMode(Message response) { 1434 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1435 unimplemented(response); 1436 } 1437 1438 /** 1439 * {@inheritDoc} 1440 */ 1441 public void sendCDMAFeatureCode(String FeatureCode, Message response) { 1442 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1443 unimplemented(response); 1444 } 1445 1446 /** 1447 * {@inheritDoc} 1448 */ 1449 public void sendCdmaSms(byte[] pdu, Message response){ 1450 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1451 } 1452 1453 public void setCdmaBroadcastActivation(boolean activate, Message response) { 1454 unimplemented(response); 1455 1456 } 1457 1458 public void getCdmaBroadcastConfig(Message response) { 1459 unimplemented(response); 1460 1461 } 1462 1463 public void setCdmaBroadcastConfig(int[] configValuesArray, Message response) { 1464 unimplemented(response); 1465 1466 } 1467 1468 public void forceDataDormancy(Message response) { 1469 unimplemented(response); 1470 } 1471 1472 1473 public void setGsmBroadcastActivation(boolean activate, Message response) { 1474 unimplemented(response); 1475 } 1476 1477 1478 public void setGsmBroadcastConfig(SmsBroadcastConfigInfo[] config, Message response) { 1479 unimplemented(response); 1480 } 1481 1482 public void getGsmBroadcastConfig(Message response) { 1483 unimplemented(response); 1484 } 1485 1486 @Override 1487 public void supplyIccPinForApp(String pin, String aid, Message response) { 1488 unimplemented(response); 1489 } 1490 1491 @Override 1492 public void supplyIccPukForApp(String puk, String newPin, String aid, Message response) { 1493 unimplemented(response); 1494 } 1495 1496 @Override 1497 public void supplyIccPin2ForApp(String pin2, String aid, Message response) { 1498 unimplemented(response); 1499 } 1500 1501 @Override 1502 public void supplyIccPuk2ForApp(String puk2, String newPin2, String aid, Message response) { 1503 unimplemented(response); 1504 } 1505 1506 @Override 1507 public void changeIccPinForApp(String oldPin, String newPin, String aidPtr, Message response) { 1508 unimplemented(response); 1509 } 1510 1511 @Override 1512 public void changeIccPin2ForApp(String oldPin2, String newPin2, String aidPtr, 1513 Message response) { 1514 unimplemented(response); 1515 } 1516 1517 public void requestIsimAuthentication(String nonce, Message response) { 1518 unimplemented(response); 1519 } 1520} 1521