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 mPinUnlockAttempts = 0; 124 mSimLockedState = SimLockState.NONE; 125 mIccStatusChangedRegistrants.notifyRegistrants(); 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 mSimLockedState = SimLockState.NONE; 166 mPukUnlockAttempts = 0; 167 mIccStatusChangedRegistrants.notifyRegistrants(); 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.RADIO_ON) && !isSimLocked()) { 445 //Log.i("GSM", "[SimCmds] getCurrentCalls"); 446 resultSuccess(result, simulatedCallState.getDriverCalls()); 447 } else { 448 //Log.i("GSM", "[SimCmds] getCurrentCalls: RADIO_OFF or 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 public void getIMSI(Message result) { 508 getIMSIForApp(null, result); 509 } 510 /** 511 * returned message 512 * retMsg.obj = AsyncResult ar 513 * ar.exception carries exception on failure 514 * ar.userObject contains the original value of result.obj 515 * ar.result is String containing IMSI on success 516 */ 517 public void getIMSIForApp(String aid, Message result) { 518 resultSuccess(result, "012345678901234"); 519 } 520 521 /** 522 * returned message 523 * retMsg.obj = AsyncResult ar 524 * ar.exception carries exception on failure 525 * ar.userObject contains the original value of result.obj 526 * ar.result is String containing IMEI on success 527 */ 528 public void getIMEI(Message result) { 529 resultSuccess(result, "012345678901234"); 530 } 531 532 /** 533 * returned message 534 * retMsg.obj = AsyncResult ar 535 * ar.exception carries exception on failure 536 * ar.userObject contains the original value of result.obj 537 * ar.result is String containing IMEISV on success 538 */ 539 public void getIMEISV(Message result) { 540 resultSuccess(result, "99"); 541 } 542 543 /** 544 * Hang up one individual connection. 545 * returned message 546 * retMsg.obj = AsyncResult ar 547 * ar.exception carries exception on failure 548 * ar.userObject contains the original value of result.obj 549 * ar.result is null on success and failure 550 * 551 * 3GPP 22.030 6.5.5 552 * "Releases a specific active call X" 553 */ 554 public void hangupConnection (int gsmIndex, Message result) { 555 boolean success; 556 557 success = simulatedCallState.onChld('1', (char)('0'+gsmIndex)); 558 559 if (!success){ 560 Log.i("GSM", "[SimCmd] hangupConnection: resultFail"); 561 resultFail(result, new RuntimeException("Hangup Error")); 562 } else { 563 Log.i("GSM", "[SimCmd] hangupConnection: resultSuccess"); 564 resultSuccess(result, null); 565 } 566 } 567 568 /** 569 * 3GPP 22.030 6.5.5 570 * "Releases all held calls or sets User Determined User Busy (UDUB) 571 * for a waiting call." 572 * ar.exception carries exception on failure 573 * ar.userObject contains the original value of result.obj 574 * ar.result is null on success and failure 575 */ 576 public void hangupWaitingOrBackground (Message result) { 577 boolean success; 578 579 success = simulatedCallState.onChld('0', '\0'); 580 581 if (!success){ 582 resultFail(result, new RuntimeException("Hangup Error")); 583 } else { 584 resultSuccess(result, null); 585 } 586 } 587 588 /** 589 * 3GPP 22.030 6.5.5 590 * "Releases all active calls (if any exist) and accepts 591 * the other (held or waiting) call." 592 * 593 * ar.exception carries exception on failure 594 * ar.userObject contains the original value of result.obj 595 * ar.result is null on success and failure 596 */ 597 public void hangupForegroundResumeBackground (Message result) { 598 boolean success; 599 600 success = simulatedCallState.onChld('1', '\0'); 601 602 if (!success){ 603 resultFail(result, new RuntimeException("Hangup Error")); 604 } else { 605 resultSuccess(result, null); 606 } 607 } 608 609 /** 610 * 3GPP 22.030 6.5.5 611 * "Places all active calls (if any exist) on hold and accepts 612 * the other (held or waiting) call." 613 * 614 * ar.exception carries exception on failure 615 * ar.userObject contains the original value of result.obj 616 * ar.result is null on success and failure 617 */ 618 public void switchWaitingOrHoldingAndActive (Message result) { 619 boolean success; 620 621 success = simulatedCallState.onChld('2', '\0'); 622 623 if (!success){ 624 resultFail(result, new RuntimeException("Hangup Error")); 625 } else { 626 resultSuccess(result, null); 627 } 628 } 629 630 /** 631 * 3GPP 22.030 6.5.5 632 * "Adds a held call to the conversation" 633 * 634 * ar.exception carries exception on failure 635 * ar.userObject contains the original value of result.obj 636 * ar.result is null on success and failure 637 */ 638 public void conference (Message result) { 639 boolean success; 640 641 success = simulatedCallState.onChld('3', '\0'); 642 643 if (!success){ 644 resultFail(result, new RuntimeException("Hangup Error")); 645 } else { 646 resultSuccess(result, null); 647 } 648 } 649 650 /** 651 * 3GPP 22.030 6.5.5 652 * "Connects the two calls and disconnects the subscriber from both calls" 653 * 654 * ar.exception carries exception on failure 655 * ar.userObject contains the original value of result.obj 656 * ar.result is null on success and failure 657 */ 658 public void explicitCallTransfer (Message result) { 659 boolean success; 660 661 success = simulatedCallState.onChld('4', '\0'); 662 663 if (!success){ 664 resultFail(result, new RuntimeException("Hangup Error")); 665 } else { 666 resultSuccess(result, null); 667 } 668 } 669 670 /** 671 * 3GPP 22.030 6.5.5 672 * "Places all active calls on hold except call X with which 673 * communication shall be supported." 674 */ 675 public void separateConnection (int gsmIndex, Message result) { 676 boolean success; 677 678 char ch = (char)(gsmIndex + '0'); 679 success = simulatedCallState.onChld('2', ch); 680 681 if (!success){ 682 resultFail(result, new RuntimeException("Hangup Error")); 683 } else { 684 resultSuccess(result, null); 685 } 686 } 687 688 /** 689 * 690 * ar.exception carries exception on failure 691 * ar.userObject contains the original value of result.obj 692 * ar.result is null on success and failure 693 */ 694 public void acceptCall (Message result) { 695 boolean success; 696 697 success = simulatedCallState.onAnswer(); 698 699 if (!success){ 700 resultFail(result, new RuntimeException("Hangup Error")); 701 } else { 702 resultSuccess(result, null); 703 } 704 } 705 706 /** 707 * also known as UDUB 708 * ar.exception carries exception on failure 709 * ar.userObject contains the original value of result.obj 710 * ar.result is null on success and failure 711 */ 712 public void rejectCall (Message result) { 713 boolean success; 714 715 success = simulatedCallState.onChld('0', '\0'); 716 717 if (!success){ 718 resultFail(result, new RuntimeException("Hangup Error")); 719 } else { 720 resultSuccess(result, null); 721 } 722 } 723 724 /** 725 * cause code returned as Integer in Message.obj.response 726 * Returns integer cause code defined in TS 24.008 727 * Annex H or closest approximation. 728 * Most significant codes: 729 * - Any defined in 22.001 F.4 (for generating busy/congestion) 730 * - Cause 68: ACM >= ACMMax 731 */ 732 public void getLastCallFailCause (Message result) { 733 int[] ret = new int[1]; 734 735 ret[0] = nextCallFailCause; 736 resultSuccess(result, ret); 737 } 738 739 /** 740 * @deprecated 741 */ 742 public void getLastPdpFailCause (Message result) { 743 unimplemented(result); 744 } 745 746 public void getLastDataCallFailCause(Message result) { 747 // 748 unimplemented(result); 749 } 750 751 public void setMute (boolean enableMute, Message result) {unimplemented(result);} 752 753 public void getMute (Message result) {unimplemented(result);} 754 755 /** 756 * response.obj is an AsyncResult 757 * response.obj.result is an int[2] 758 * response.obj.result[0] is received signal strength (0-31, 99) 759 * response.obj.result[1] is bit error rate (0-7, 99) 760 * as defined in TS 27.007 8.5 761 */ 762 public void getSignalStrength (Message result) { 763 int ret[] = new int[2]; 764 765 ret[0] = 23; 766 ret[1] = 0; 767 768 resultSuccess(result, ret); 769 } 770 771 /** 772 * Assign a specified band for RF configuration. 773 * 774 * @param bandMode one of BM_*_BAND 775 * @param result is callback message 776 */ 777 public void setBandMode (int bandMode, Message result) { 778 resultSuccess(result, null); 779 } 780 781 /** 782 * Query the list of band mode supported by RF. 783 * 784 * @param result is callback message 785 * ((AsyncResult)response.obj).result is an int[] with every 786 * element representing one available BM_*_BAND 787 */ 788 public void queryAvailableBandMode (Message result) { 789 int ret[] = new int [4]; 790 791 ret[0] = 4; 792 ret[1] = Phone.BM_US_BAND; 793 ret[2] = Phone.BM_JPN_BAND; 794 ret[3] = Phone.BM_AUS_BAND; 795 796 resultSuccess(result, ret); 797 } 798 799 /** 800 * {@inheritDoc} 801 */ 802 public void sendTerminalResponse(String contents, Message response) { 803 resultSuccess(response, null); 804 } 805 806 /** 807 * {@inheritDoc} 808 */ 809 public void sendEnvelope(String contents, Message response) { 810 resultSuccess(response, null); 811 } 812 813 /** 814 * {@inheritDoc} 815 */ 816 public void sendEnvelopeWithStatus(String contents, Message response) { 817 resultSuccess(response, null); 818 } 819 820 /** 821 * {@inheritDoc} 822 */ 823 public void handleCallSetupRequestFromSim( 824 boolean accept, Message response) { 825 resultSuccess(response, null); 826 } 827 828 /** 829 * response.obj.result is an String[14] 830 * See ril.h for details 831 * 832 * Please note that registration state 4 ("unknown") is treated 833 * as "out of service" above 834 */ 835 public void getVoiceRegistrationState (Message result) { 836 String ret[] = new String[14]; 837 838 ret[0] = "5"; // registered roam 839 ret[1] = null; 840 ret[2] = null; 841 ret[3] = null; 842 ret[4] = null; 843 ret[5] = null; 844 ret[6] = null; 845 ret[7] = null; 846 ret[8] = null; 847 ret[9] = null; 848 ret[10] = null; 849 ret[11] = null; 850 ret[12] = null; 851 ret[13] = null; 852 853 resultSuccess(result, ret); 854 } 855 856 /** 857 * response.obj.result is an String[4] 858 * response.obj.result[0] is registration state 0-5 from TS 27.007 7.2 859 * response.obj.result[1] is LAC if registered or NULL if not 860 * response.obj.result[2] is CID if registered or NULL if not 861 * response.obj.result[3] indicates the available radio technology, where: 862 * 0 == unknown 863 * 1 == GPRS only 864 * 2 == EDGE 865 * 3 == UMTS 866 * 867 * valid LAC are 0x0000 - 0xffff 868 * valid CID are 0x00000000 - 0xffffffff 869 * 870 * Please note that registration state 4 ("unknown") is treated 871 * as "out of service" in the Android telephony system 872 */ 873 public void getDataRegistrationState (Message result) { 874 String ret[] = new String[4]; 875 876 ret[0] = "5"; // registered roam 877 ret[1] = null; 878 ret[2] = null; 879 ret[3] = "2"; 880 881 resultSuccess(result, ret); 882 } 883 884 /** 885 * response.obj.result is a String[3] 886 * response.obj.result[0] is long alpha or null if unregistered 887 * response.obj.result[1] is short alpha or null if unregistered 888 * response.obj.result[2] is numeric or null if unregistered 889 */ 890 public void getOperator(Message result) { 891 String[] ret = new String[3]; 892 893 ret[0] = "El Telco Loco"; 894 ret[1] = "Telco Loco"; 895 ret[2] = "001001"; 896 897 resultSuccess(result, ret); 898 } 899 900 /** 901 * ar.exception carries exception on failure 902 * ar.userObject contains the original value of result.obj 903 * ar.result is null on success and failure 904 */ 905 public void sendDtmf(char c, Message result) { 906 resultSuccess(result, null); 907 } 908 909 /** 910 * ar.exception carries exception on failure 911 * ar.userObject contains the original value of result.obj 912 * ar.result is null on success and failure 913 */ 914 public void startDtmf(char c, Message result) { 915 resultSuccess(result, null); 916 } 917 918 /** 919 * ar.exception carries exception on failure 920 * ar.userObject contains the original value of result.obj 921 * ar.result is null on success and failure 922 */ 923 public void stopDtmf(Message result) { 924 resultSuccess(result, null); 925 } 926 927 /** 928 * ar.exception carries exception on failure 929 * ar.userObject contains the original value of result.obj 930 * ar.result is null on success and failure 931 */ 932 public void sendBurstDtmf(String dtmfString, int on, int off, Message result) { 933 resultSuccess(result, null); 934 } 935 936 /** 937 * smscPDU is smsc address in PDU form GSM BCD format prefixed 938 * by a length byte (as expected by TS 27.005) or NULL for default SMSC 939 * pdu is SMS in PDU format as an ASCII hex string 940 * less the SMSC address 941 */ 942 public void sendSMS (String smscPDU, String pdu, Message result) {unimplemented(result);} 943 944 public void deleteSmsOnSim(int index, Message response) { 945 Log.d(LOG_TAG, "Delete message at index " + index); 946 unimplemented(response); 947 } 948 949 public void deleteSmsOnRuim(int index, Message response) { 950 Log.d(LOG_TAG, "Delete RUIM message at index " + index); 951 unimplemented(response); 952 } 953 954 public void writeSmsToSim(int status, String smsc, String pdu, Message response) { 955 Log.d(LOG_TAG, "Write SMS to SIM with status " + status); 956 unimplemented(response); 957 } 958 959 public void writeSmsToRuim(int status, String pdu, Message response) { 960 Log.d(LOG_TAG, "Write SMS to RUIM with status " + status); 961 unimplemented(response); 962 } 963 964 public void setupDataCall(String radioTechnology, String profile, 965 String apn, String user, String password, String authType, 966 String protocol, Message result) { 967 unimplemented(result); 968 } 969 970 public void deactivateDataCall(int cid, int reason, Message result) {unimplemented(result);} 971 972 public void setPreferredNetworkType(int networkType , Message result) { 973 mNetworkType = networkType; 974 resultSuccess(result, null); 975 } 976 977 public void getPreferredNetworkType(Message result) { 978 int ret[] = new int[1]; 979 980 ret[0] = mNetworkType; 981 resultSuccess(result, ret); 982 } 983 984 public void getNeighboringCids(Message result) { 985 int ret[] = new int[7]; 986 987 ret[0] = 6; 988 for (int i = 1; i<7; i++) { 989 ret[i] = i; 990 } 991 resultSuccess(result, ret); 992 } 993 994 public void setLocationUpdates(boolean enable, Message response) { 995 unimplemented(response); 996 } 997 998 public void getSmscAddress(Message result) { 999 unimplemented(result); 1000 } 1001 1002 public void setSmscAddress(String address, Message result) { 1003 unimplemented(result); 1004 } 1005 1006 public void reportSmsMemoryStatus(boolean available, Message result) { 1007 unimplemented(result); 1008 } 1009 1010 public void reportStkServiceIsRunning(Message result) { 1011 resultSuccess(result, null); 1012 } 1013 1014 @Override 1015 public void getCdmaSubscriptionSource(Message result) { 1016 unimplemented(result); 1017 } 1018 1019 private boolean isSimLocked() { 1020 if (mSimLockedState != SimLockState.NONE) { 1021 return true; 1022 } 1023 return false; 1024 } 1025 1026 public void setRadioPower(boolean on, Message result) { 1027 if(on) { 1028 setRadioState(RadioState.RADIO_ON); 1029 } else { 1030 setRadioState(RadioState.RADIO_OFF); 1031 } 1032 } 1033 1034 1035 public void acknowledgeLastIncomingGsmSms(boolean success, int cause, Message result) { 1036 unimplemented(result); 1037 } 1038 1039 public void acknowledgeLastIncomingCdmaSms(boolean success, int cause, Message result) { 1040 unimplemented(result); 1041 } 1042 1043 public void acknowledgeIncomingGsmSmsWithPdu(boolean success, String ackPdu, 1044 Message result) { 1045 unimplemented(result); 1046 } 1047 1048 public void iccIO(int command, int fileid, String path, int p1, int p2, int p3, String data, 1049 String pin2, Message response) { 1050 iccIOForApp(command, fileid, path, p1, p2, p3, data,pin2, null, response); 1051 } 1052 1053 /** 1054 * parameters equivalent to 27.007 AT+CRSM command 1055 * response.obj will be an AsyncResult 1056 * response.obj.userObj will be a SimIoResult on success 1057 */ 1058 public void iccIOForApp (int command, int fileid, String path, int p1, int p2, 1059 int p3, String data, String pin2, String aid, Message result) { 1060 unimplemented(result); 1061 } 1062 1063 /** 1064 * (AsyncResult)response.obj).result is an int[] with element [0] set to 1065 * 1 for "CLIP is provisioned", and 0 for "CLIP is not provisioned". 1066 * 1067 * @param response is callback message 1068 */ 1069 public void queryCLIP(Message response) { unimplemented(response); } 1070 1071 1072 /** 1073 * response.obj will be a an int[2] 1074 * 1075 * response.obj[0] will be TS 27.007 +CLIR parameter 'n' 1076 * 0 presentation indicator is used according to the subscription of the CLIR service 1077 * 1 CLIR invocation 1078 * 2 CLIR suppression 1079 * 1080 * response.obj[1] will be TS 27.007 +CLIR parameter 'm' 1081 * 0 CLIR not provisioned 1082 * 1 CLIR provisioned in permanent mode 1083 * 2 unknown (e.g. no network, etc.) 1084 * 3 CLIR temporary mode presentation restricted 1085 * 4 CLIR temporary mode presentation allowed 1086 */ 1087 1088 public void getCLIR(Message result) {unimplemented(result);} 1089 1090 /** 1091 * clirMode is one of the CLIR_* constants above 1092 * 1093 * response.obj is null 1094 */ 1095 1096 public void setCLIR(int clirMode, Message result) {unimplemented(result);} 1097 1098 /** 1099 * (AsyncResult)response.obj).result is an int[] with element [0] set to 1100 * 0 for disabled, 1 for enabled. 1101 * 1102 * @param serviceClass is a sum of SERVICE_CLASS_* 1103 * @param response is callback message 1104 */ 1105 1106 public void queryCallWaiting(int serviceClass, Message response) { 1107 unimplemented(response); 1108 } 1109 1110 /** 1111 * @param enable is true to enable, false to disable 1112 * @param serviceClass is a sum of SERVICE_CLASS_* 1113 * @param response is callback message 1114 */ 1115 1116 public void setCallWaiting(boolean enable, int serviceClass, 1117 Message response) { 1118 unimplemented(response); 1119 } 1120 1121 /** 1122 * @param action is one of CF_ACTION_* 1123 * @param cfReason is one of CF_REASON_* 1124 * @param serviceClass is a sum of SERVICE_CLASSS_* 1125 */ 1126 public void setCallForward(int action, int cfReason, int serviceClass, 1127 String number, int timeSeconds, Message result) {unimplemented(result);} 1128 1129 /** 1130 * cfReason is one of CF_REASON_* 1131 * 1132 * ((AsyncResult)response.obj).result will be an array of 1133 * CallForwardInfo's 1134 * 1135 * An array of length 0 means "disabled for all codes" 1136 */ 1137 public void queryCallForwardStatus(int cfReason, int serviceClass, 1138 String number, Message result) {unimplemented(result);} 1139 1140 public void setNetworkSelectionModeAutomatic(Message result) {unimplemented(result);} 1141 public void exitEmergencyCallbackMode(Message result) {unimplemented(result);} 1142 public void setNetworkSelectionModeManual( 1143 String operatorNumeric, Message result) {unimplemented(result);} 1144 1145 /** 1146 * Queries whether the current network selection mode is automatic 1147 * or manual 1148 * 1149 * ((AsyncResult)response.obj).result is an int[] with element [0] being 1150 * a 0 for automatic selection and a 1 for manual selection 1151 */ 1152 1153 public void getNetworkSelectionMode(Message result) { 1154 int ret[] = new int[1]; 1155 1156 ret[0] = 0; 1157 resultSuccess(result, ret); 1158 } 1159 1160 /** 1161 * Queries the currently available networks 1162 * 1163 * ((AsyncResult)response.obj).result is a List of NetworkInfo objects 1164 */ 1165 public void getAvailableNetworks(Message result) {unimplemented(result);} 1166 1167 public void getBasebandVersion (Message result) { 1168 resultSuccess(result, "SimulatedCommands"); 1169 } 1170 1171 /** 1172 * Simulates an incoming USSD message 1173 * @param statusCode Status code string. See <code>setOnUSSD</code> 1174 * in CommandsInterface.java 1175 * @param message Message text to send or null if none 1176 */ 1177 public void triggerIncomingUssd(String statusCode, String message) { 1178 if (mUSSDRegistrant != null) { 1179 String[] result = {statusCode, message}; 1180 mUSSDRegistrant.notifyResult(result); 1181 } 1182 } 1183 1184 1185 public void sendUSSD (String ussdString, Message result) { 1186 1187 // We simulate this particular sequence 1188 if (ussdString.equals("#646#")) { 1189 resultSuccess(result, null); 1190 1191 // 0 == USSD-Notify 1192 triggerIncomingUssd("0", "You have NNN minutes remaining."); 1193 } else { 1194 resultSuccess(result, null); 1195 1196 triggerIncomingUssd("0", "All Done"); 1197 } 1198 } 1199 1200 // inherited javadoc suffices 1201 public void cancelPendingUssd (Message response) { 1202 resultSuccess(response, null); 1203 } 1204 1205 1206 public void resetRadio(Message result) { 1207 unimplemented(result); 1208 } 1209 1210 public void invokeOemRilRequestRaw(byte[] data, Message response) { 1211 // Just echo back data 1212 if (response != null) { 1213 AsyncResult.forMessage(response).result = data; 1214 response.sendToTarget(); 1215 } 1216 } 1217 1218 public void invokeOemRilRequestStrings(String[] strings, Message response) { 1219 // Just echo back data 1220 if (response != null) { 1221 AsyncResult.forMessage(response).result = strings; 1222 response.sendToTarget(); 1223 } 1224 } 1225 1226 //***** SimulatedRadioControl 1227 1228 1229 /** Start the simulated phone ringing */ 1230 public void 1231 triggerRing(String number) { 1232 simulatedCallState.triggerRing(number); 1233 mCallStateRegistrants.notifyRegistrants(); 1234 } 1235 1236 public void 1237 progressConnectingCallState() { 1238 simulatedCallState.progressConnectingCallState(); 1239 mCallStateRegistrants.notifyRegistrants(); 1240 } 1241 1242 /** If a call is DIALING or ALERTING, progress it all the way to ACTIVE */ 1243 public void 1244 progressConnectingToActive() { 1245 simulatedCallState.progressConnectingToActive(); 1246 mCallStateRegistrants.notifyRegistrants(); 1247 } 1248 1249 /** automatically progress mobile originated calls to ACTIVE. 1250 * default to true 1251 */ 1252 public void 1253 setAutoProgressConnectingCall(boolean b) { 1254 simulatedCallState.setAutoProgressConnectingCall(b); 1255 } 1256 1257 public void 1258 setNextDialFailImmediately(boolean b) { 1259 simulatedCallState.setNextDialFailImmediately(b); 1260 } 1261 1262 public void 1263 setNextCallFailCause(int gsmCause) { 1264 nextCallFailCause = gsmCause; 1265 } 1266 1267 public void 1268 triggerHangupForeground() { 1269 simulatedCallState.triggerHangupForeground(); 1270 mCallStateRegistrants.notifyRegistrants(); 1271 } 1272 1273 /** hangup holding calls */ 1274 public void 1275 triggerHangupBackground() { 1276 simulatedCallState.triggerHangupBackground(); 1277 mCallStateRegistrants.notifyRegistrants(); 1278 } 1279 1280 public void triggerSsn(int type, int code) { 1281 SuppServiceNotification not = new SuppServiceNotification(); 1282 not.notificationType = type; 1283 not.code = code; 1284 mSsnRegistrant.notifyRegistrant(new AsyncResult(null, not, null)); 1285 } 1286 1287 public void 1288 shutdown() { 1289 setRadioState(RadioState.RADIO_UNAVAILABLE); 1290 Looper looper = mHandlerThread.getLooper(); 1291 if (looper != null) { 1292 looper.quit(); 1293 } 1294 } 1295 1296 /** hangup all */ 1297 1298 public void 1299 triggerHangupAll() { 1300 simulatedCallState.triggerHangupAll(); 1301 mCallStateRegistrants.notifyRegistrants(); 1302 } 1303 1304 public void 1305 triggerIncomingSMS(String message) { 1306 //TODO 1307 } 1308 1309 public void 1310 pauseResponses() { 1311 pausedResponseCount++; 1312 } 1313 1314 public void 1315 resumeResponses() { 1316 pausedResponseCount--; 1317 1318 if (pausedResponseCount == 0) { 1319 for (int i = 0, s = pausedResponses.size(); i < s ; i++) { 1320 pausedResponses.get(i).sendToTarget(); 1321 } 1322 pausedResponses.clear(); 1323 } else { 1324 Log.e("GSM", "SimulatedCommands.resumeResponses < 0"); 1325 } 1326 } 1327 1328 //***** Private Methods 1329 1330 private void unimplemented(Message result) { 1331 if (result != null) { 1332 AsyncResult.forMessage(result).exception 1333 = new RuntimeException("Unimplemented"); 1334 1335 if (pausedResponseCount > 0) { 1336 pausedResponses.add(result); 1337 } else { 1338 result.sendToTarget(); 1339 } 1340 } 1341 } 1342 1343 private void resultSuccess(Message result, Object ret) { 1344 if (result != null) { 1345 AsyncResult.forMessage(result).result = ret; 1346 if (pausedResponseCount > 0) { 1347 pausedResponses.add(result); 1348 } else { 1349 result.sendToTarget(); 1350 } 1351 } 1352 } 1353 1354 private void resultFail(Message result, Throwable tr) { 1355 if (result != null) { 1356 AsyncResult.forMessage(result).exception = tr; 1357 if (pausedResponseCount > 0) { 1358 pausedResponses.add(result); 1359 } else { 1360 result.sendToTarget(); 1361 } 1362 } 1363 } 1364 1365 // ***** Methods for CDMA support 1366 public void 1367 getDeviceIdentity(Message response) { 1368 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1369 unimplemented(response); 1370 } 1371 1372 public void 1373 getCDMASubscription(Message response) { 1374 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1375 unimplemented(response); 1376 } 1377 1378 public void 1379 setCdmaSubscriptionSource(int cdmaSubscriptionType, Message response) { 1380 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1381 unimplemented(response); 1382 } 1383 1384 public void queryCdmaRoamingPreference(Message response) { 1385 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1386 unimplemented(response); 1387 } 1388 1389 public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) { 1390 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1391 unimplemented(response); 1392 } 1393 1394 public void 1395 setPhoneType(int phoneType) { 1396 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1397 } 1398 1399 public void getPreferredVoicePrivacy(Message result) { 1400 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1401 unimplemented(result); 1402 } 1403 1404 public void setPreferredVoicePrivacy(boolean enable, Message result) { 1405 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1406 unimplemented(result); 1407 } 1408 1409 /** 1410 * Set the TTY mode 1411 * 1412 * @param ttyMode is one of the following: 1413 * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} 1414 * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} 1415 * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} 1416 * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO} 1417 * @param response is callback message 1418 */ 1419 public void setTTYMode(int ttyMode, Message response) { 1420 Log.w(LOG_TAG, "Not implemented in SimulatedCommands"); 1421 unimplemented(response); 1422 } 1423 1424 /** 1425 * Query the TTY mode 1426 * (AsyncResult)response.obj).result is an int[] with element [0] set to 1427 * tty mode: 1428 * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} 1429 * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} 1430 * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} 1431 * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO} 1432 * @param response is callback message 1433 */ 1434 public void queryTTYMode(Message response) { 1435 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1436 unimplemented(response); 1437 } 1438 1439 /** 1440 * {@inheritDoc} 1441 */ 1442 public void sendCDMAFeatureCode(String FeatureCode, Message response) { 1443 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1444 unimplemented(response); 1445 } 1446 1447 /** 1448 * {@inheritDoc} 1449 */ 1450 public void sendCdmaSms(byte[] pdu, Message response){ 1451 Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands"); 1452 } 1453 1454 public void setCdmaBroadcastActivation(boolean activate, Message response) { 1455 unimplemented(response); 1456 1457 } 1458 1459 public void getCdmaBroadcastConfig(Message response) { 1460 unimplemented(response); 1461 1462 } 1463 1464 public void setCdmaBroadcastConfig(int[] configValuesArray, Message response) { 1465 unimplemented(response); 1466 1467 } 1468 1469 public void forceDataDormancy(Message response) { 1470 unimplemented(response); 1471 } 1472 1473 1474 public void setGsmBroadcastActivation(boolean activate, Message response) { 1475 unimplemented(response); 1476 } 1477 1478 1479 public void setGsmBroadcastConfig(SmsBroadcastConfigInfo[] config, Message response) { 1480 unimplemented(response); 1481 } 1482 1483 public void getGsmBroadcastConfig(Message response) { 1484 unimplemented(response); 1485 } 1486 1487 @Override 1488 public void supplyIccPinForApp(String pin, String aid, Message response) { 1489 unimplemented(response); 1490 } 1491 1492 @Override 1493 public void supplyIccPukForApp(String puk, String newPin, String aid, Message response) { 1494 unimplemented(response); 1495 } 1496 1497 @Override 1498 public void supplyIccPin2ForApp(String pin2, String aid, Message response) { 1499 unimplemented(response); 1500 } 1501 1502 @Override 1503 public void supplyIccPuk2ForApp(String puk2, String newPin2, String aid, Message response) { 1504 unimplemented(response); 1505 } 1506 1507 @Override 1508 public void changeIccPinForApp(String oldPin, String newPin, String aidPtr, Message response) { 1509 unimplemented(response); 1510 } 1511 1512 @Override 1513 public void changeIccPin2ForApp(String oldPin2, String newPin2, String aidPtr, 1514 Message response) { 1515 unimplemented(response); 1516 } 1517 1518 public void requestIsimAuthentication(String nonce, Message response) { 1519 unimplemented(response); 1520 } 1521 1522 public void getVoiceRadioTechnology(Message response) { 1523 unimplemented(response); 1524 } 1525} 1526