1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony.cat; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.os.AsyncResult; 22 import android.os.Handler; 23 import android.os.HandlerThread; 24 import android.os.Message; 25 import android.os.SystemProperties; 26 27 import com.android.internal.telephony.IccUtils; 28 import com.android.internal.telephony.CommandsInterface; 29 import com.android.internal.telephony.IccCard; 30 import com.android.internal.telephony.IccFileHandler; 31 import com.android.internal.telephony.IccRecords; 32 33 34 import java.io.ByteArrayOutputStream; 35 import java.util.Locale; 36 37 class RilMessage { 38 int mId; 39 Object mData; 40 ResultCode mResCode; 41 42 RilMessage(int msgId, String rawData) { 43 mId = msgId; 44 mData = rawData; 45 } 46 47 RilMessage(RilMessage other) { 48 this.mId = other.mId; 49 this.mData = other.mData; 50 this.mResCode = other.mResCode; 51 } 52 } 53 54 /** 55 * Class that implements SIM Toolkit Telephony Service. Interacts with the RIL 56 * and application. 57 * 58 * {@hide} 59 */ 60 public class CatService extends Handler implements AppInterface { 61 62 // Class members 63 private static IccRecords mIccRecords; 64 65 // Service members. 66 // Protects singleton instance lazy initialization. 67 private static final Object sInstanceLock = new Object(); 68 private static CatService sInstance; 69 private CommandsInterface mCmdIf; 70 private Context mContext; 71 private CatCmdMessage mCurrntCmd = null; 72 private CatCmdMessage mMenuCmd = null; 73 74 private RilMessageDecoder mMsgDecoder = null; 75 76 // Service constants. 77 static final int MSG_ID_SESSION_END = 1; 78 static final int MSG_ID_PROACTIVE_COMMAND = 2; 79 static final int MSG_ID_EVENT_NOTIFY = 3; 80 static final int MSG_ID_CALL_SETUP = 4; 81 static final int MSG_ID_REFRESH = 5; 82 static final int MSG_ID_RESPONSE = 6; 83 static final int MSG_ID_SIM_READY = 7; 84 85 static final int MSG_ID_RIL_MSG_DECODED = 10; 86 87 // Events to signal SIM presence or absent in the device. 88 private static final int MSG_ID_ICC_RECORDS_LOADED = 20; 89 90 private static final int DEV_ID_KEYPAD = 0x01; 91 private static final int DEV_ID_DISPLAY = 0x02; 92 private static final int DEV_ID_EARPIECE = 0x03; 93 private static final int DEV_ID_UICC = 0x81; 94 private static final int DEV_ID_TERMINAL = 0x82; 95 private static final int DEV_ID_NETWORK = 0x83; 96 97 static final String STK_DEFAULT = "Defualt Message"; 98 99 /* Intentionally private for singleton */ 100 private CatService(CommandsInterface ci, IccRecords ir, Context context, 101 IccFileHandler fh, IccCard ic) { 102 if (ci == null || ir == null || context == null || fh == null 103 || ic == null) { 104 throw new NullPointerException( 105 "Service: Input parameters must not be null"); 106 } 107 mCmdIf = ci; 108 mContext = context; 109 110 // Get the RilMessagesDecoder for decoding the messages. 111 mMsgDecoder = RilMessageDecoder.getInstance(this, fh); 112 113 // Register ril events handling. 114 mCmdIf.setOnCatSessionEnd(this, MSG_ID_SESSION_END, null); 115 mCmdIf.setOnCatProactiveCmd(this, MSG_ID_PROACTIVE_COMMAND, null); 116 mCmdIf.setOnCatEvent(this, MSG_ID_EVENT_NOTIFY, null); 117 mCmdIf.setOnCatCallSetUp(this, MSG_ID_CALL_SETUP, null); 118 //mCmdIf.setOnSimRefresh(this, MSG_ID_REFRESH, null); 119 120 mIccRecords = ir; 121 122 // Register for SIM ready event. 123 mCmdIf.registerForSIMReady(this, MSG_ID_SIM_READY, null); 124 mCmdIf.registerForRUIMReady(this, MSG_ID_SIM_READY, null); 125 mCmdIf.registerForNVReady(this, MSG_ID_SIM_READY, null); 126 mIccRecords.registerForRecordsLoaded(this, MSG_ID_ICC_RECORDS_LOADED, null); 127 128 CatLog.d(this, "Is running"); 129 } 130 131 public void dispose() { 132 mIccRecords.unregisterForRecordsLoaded(this); 133 mCmdIf.unSetOnCatSessionEnd(this); 134 mCmdIf.unSetOnCatProactiveCmd(this); 135 mCmdIf.unSetOnCatEvent(this); 136 mCmdIf.unSetOnCatCallSetUp(this); 137 138 this.removeCallbacksAndMessages(null); 139 } 140 141 protected void finalize() { 142 CatLog.d(this, "Service finalized"); 143 } 144 145 private void handleRilMsg(RilMessage rilMsg) { 146 if (rilMsg == null) { 147 return; 148 } 149 150 // dispatch messages 151 CommandParams cmdParams = null; 152 switch (rilMsg.mId) { 153 case MSG_ID_EVENT_NOTIFY: 154 if (rilMsg.mResCode == ResultCode.OK) { 155 cmdParams = (CommandParams) rilMsg.mData; 156 if (cmdParams != null) { 157 handleProactiveCommand(cmdParams); 158 } 159 } 160 break; 161 case MSG_ID_PROACTIVE_COMMAND: 162 try { 163 cmdParams = (CommandParams) rilMsg.mData; 164 } catch (ClassCastException e) { 165 // for error handling : cast exception 166 CatLog.d(this, "Fail to parse proactive command"); 167 sendTerminalResponse(mCurrntCmd.mCmdDet, ResultCode.CMD_DATA_NOT_UNDERSTOOD, 168 false, 0x00, null); 169 break; 170 } 171 if (cmdParams != null) { 172 if (rilMsg.mResCode == ResultCode.OK) { 173 handleProactiveCommand(cmdParams); 174 } else { 175 // for proactive commands that couldn't be decoded 176 // successfully respond with the code generated by the 177 // message decoder. 178 sendTerminalResponse(cmdParams.cmdDet, rilMsg.mResCode, 179 false, 0, null); 180 } 181 } 182 break; 183 case MSG_ID_REFRESH: 184 cmdParams = (CommandParams) rilMsg.mData; 185 if (cmdParams != null) { 186 handleProactiveCommand(cmdParams); 187 } 188 break; 189 case MSG_ID_SESSION_END: 190 handleSessionEnd(); 191 break; 192 case MSG_ID_CALL_SETUP: 193 // prior event notify command supplied all the information 194 // needed for set up call processing. 195 break; 196 } 197 } 198 199 /** 200 * Handles RIL_UNSOL_STK_PROACTIVE_COMMAND unsolicited command from RIL. 201 * Sends valid proactive command data to the application using intents. 202 * 203 */ 204 private void handleProactiveCommand(CommandParams cmdParams) { 205 CatLog.d(this, cmdParams.getCommandType().name()); 206 207 CharSequence message; 208 CatCmdMessage cmdMsg = new CatCmdMessage(cmdParams); 209 switch (cmdParams.getCommandType()) { 210 case SET_UP_MENU: 211 if (removeMenu(cmdMsg.getMenu())) { 212 mMenuCmd = null; 213 } else { 214 mMenuCmd = cmdMsg; 215 } 216 sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null); 217 break; 218 case DISPLAY_TEXT: 219 // when application is not required to respond, send an immediate response. 220 if (!cmdMsg.geTextMessage().responseNeeded) { 221 sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null); 222 } 223 break; 224 case REFRESH: 225 // ME side only handles refresh commands which meant to remove IDLE 226 // MODE TEXT. 227 cmdParams.cmdDet.typeOfCommand = CommandType.SET_UP_IDLE_MODE_TEXT.value(); 228 break; 229 case SET_UP_IDLE_MODE_TEXT: 230 sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null); 231 break; 232 case PROVIDE_LOCAL_INFORMATION: 233 ResponseData resp; 234 switch (cmdParams.cmdDet.commandQualifier) { 235 case CommandParamsFactory.DTTZ_SETTING: 236 resp = new DTTZResponseData(null); 237 sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, resp); 238 return; 239 case CommandParamsFactory.LANGUAGE_SETTING: 240 resp = new LanguageResponseData(Locale.getDefault().getLanguage()); 241 sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, resp); 242 return; 243 default: 244 sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null); 245 return; 246 } 247 case LAUNCH_BROWSER: 248 if ((((LaunchBrowserParams) cmdParams).confirmMsg.text != null) 249 && (((LaunchBrowserParams) cmdParams).confirmMsg.text.equals(STK_DEFAULT))) { 250 message = mContext.getText(com.android.internal.R.string.launchBrowserDefault); 251 ((LaunchBrowserParams) cmdParams).confirmMsg.text = message.toString(); 252 } 253 break; 254 case SELECT_ITEM: 255 case GET_INPUT: 256 case GET_INKEY: 257 break; 258 case SEND_DTMF: 259 case SEND_SMS: 260 case SEND_SS: 261 case SEND_USSD: 262 if ((((DisplayTextParams)cmdParams).textMsg.text != null) 263 && (((DisplayTextParams)cmdParams).textMsg.text.equals(STK_DEFAULT))) { 264 message = mContext.getText(com.android.internal.R.string.sending); 265 ((DisplayTextParams)cmdParams).textMsg.text = message.toString(); 266 } 267 break; 268 case PLAY_TONE: 269 break; 270 case SET_UP_CALL: 271 if ((((CallSetupParams) cmdParams).confirmMsg.text != null) 272 && (((CallSetupParams) cmdParams).confirmMsg.text.equals(STK_DEFAULT))) { 273 message = mContext.getText(com.android.internal.R.string.SetupCallDefault); 274 ((CallSetupParams) cmdParams).confirmMsg.text = message.toString(); 275 } 276 break; 277 default: 278 CatLog.d(this, "Unsupported command"); 279 return; 280 } 281 mCurrntCmd = cmdMsg; 282 Intent intent = new Intent(AppInterface.CAT_CMD_ACTION); 283 intent.putExtra("STK CMD", cmdMsg); 284 mContext.sendBroadcast(intent); 285 } 286 287 /** 288 * Handles RIL_UNSOL_STK_SESSION_END unsolicited command from RIL. 289 * 290 */ 291 private void handleSessionEnd() { 292 CatLog.d(this, "SESSION END"); 293 294 mCurrntCmd = mMenuCmd; 295 Intent intent = new Intent(AppInterface.CAT_SESSION_END_ACTION); 296 mContext.sendBroadcast(intent); 297 } 298 299 private void sendTerminalResponse(CommandDetails cmdDet, 300 ResultCode resultCode, boolean includeAdditionalInfo, 301 int additionalInfo, ResponseData resp) { 302 303 if (cmdDet == null) { 304 return; 305 } 306 ByteArrayOutputStream buf = new ByteArrayOutputStream(); 307 308 Input cmdInput = null; 309 if (mCurrntCmd != null) { 310 cmdInput = mCurrntCmd.geInput(); 311 } 312 313 // command details 314 int tag = ComprehensionTlvTag.COMMAND_DETAILS.value(); 315 if (cmdDet.compRequired) { 316 tag |= 0x80; 317 } 318 buf.write(tag); 319 buf.write(0x03); // length 320 buf.write(cmdDet.commandNumber); 321 buf.write(cmdDet.typeOfCommand); 322 buf.write(cmdDet.commandQualifier); 323 324 // device identities 325 // According to TS102.223/TS31.111 section 6.8 Structure of 326 // TERMINAL RESPONSE, "For all SIMPLE-TLV objects with Min=N, 327 // the ME should set the CR(comprehension required) flag to 328 // comprehension not required.(CR=0)" 329 // Since DEVICE_IDENTITIES and DURATION TLVs have Min=N, 330 // the CR flag is not set. 331 tag = ComprehensionTlvTag.DEVICE_IDENTITIES.value(); 332 buf.write(tag); 333 buf.write(0x02); // length 334 buf.write(DEV_ID_TERMINAL); // source device id 335 buf.write(DEV_ID_UICC); // destination device id 336 337 // result 338 tag = 0x80 | ComprehensionTlvTag.RESULT.value(); 339 buf.write(tag); 340 int length = includeAdditionalInfo ? 2 : 1; 341 buf.write(length); 342 buf.write(resultCode.value()); 343 344 // additional info 345 if (includeAdditionalInfo) { 346 buf.write(additionalInfo); 347 } 348 349 // Fill optional data for each corresponding command 350 if (resp != null) { 351 resp.format(buf); 352 } else { 353 encodeOptionalTags(cmdDet, resultCode, cmdInput, buf); 354 } 355 356 byte[] rawData = buf.toByteArray(); 357 String hexString = IccUtils.bytesToHexString(rawData); 358 if (false) { 359 CatLog.d(this, "TERMINAL RESPONSE: " + hexString); 360 } 361 362 mCmdIf.sendTerminalResponse(hexString, null); 363 } 364 365 private void encodeOptionalTags(CommandDetails cmdDet, 366 ResultCode resultCode, Input cmdInput, ByteArrayOutputStream buf) { 367 CommandType cmdType = AppInterface.CommandType.fromInt(cmdDet.typeOfCommand); 368 if (cmdType != null) { 369 switch (cmdType) { 370 case GET_INKEY: 371 // ETSI TS 102 384,27.22.4.2.8.4.2. 372 // If it is a response for GET_INKEY command and the response timeout 373 // occured, then add DURATION TLV for variable timeout case. 374 if ((resultCode.value() == ResultCode.NO_RESPONSE_FROM_USER.value()) && 375 (cmdInput != null) && (cmdInput.duration != null)) { 376 getInKeyResponse(buf, cmdInput); 377 } 378 break; 379 case PROVIDE_LOCAL_INFORMATION: 380 if ((cmdDet.commandQualifier == CommandParamsFactory.LANGUAGE_SETTING) && 381 (resultCode.value() == ResultCode.OK.value())) { 382 getPliResponse(buf); 383 } 384 break; 385 default: 386 CatLog.d(this, "encodeOptionalTags() Unsupported Cmd:" + cmdDet.typeOfCommand); 387 break; 388 } 389 } else { 390 CatLog.d(this, "encodeOptionalTags() bad Cmd:" + cmdDet.typeOfCommand); 391 } 392 } 393 394 private void getInKeyResponse(ByteArrayOutputStream buf, Input cmdInput) { 395 int tag = ComprehensionTlvTag.DURATION.value(); 396 397 buf.write(tag); 398 buf.write(0x02); // length 399 buf.write(cmdInput.duration.timeUnit.SECOND.value()); // Time (Unit,Seconds) 400 buf.write(cmdInput.duration.timeInterval); // Time Duration 401 } 402 403 private void getPliResponse(ByteArrayOutputStream buf) { 404 405 // Locale Language Setting 406 String lang = SystemProperties.get("persist.sys.language"); 407 408 if (lang != null) { 409 // tag 410 int tag = ComprehensionTlvTag.LANGUAGE.value(); 411 buf.write(tag); 412 ResponseData.writeLength(buf, lang.length()); 413 buf.write(lang.getBytes(), 0, lang.length()); 414 } 415 } 416 417 private void sendMenuSelection(int menuId, boolean helpRequired) { 418 419 ByteArrayOutputStream buf = new ByteArrayOutputStream(); 420 421 // tag 422 int tag = BerTlv.BER_MENU_SELECTION_TAG; 423 buf.write(tag); 424 425 // length 426 buf.write(0x00); // place holder 427 428 // device identities 429 tag = 0x80 | ComprehensionTlvTag.DEVICE_IDENTITIES.value(); 430 buf.write(tag); 431 buf.write(0x02); // length 432 buf.write(DEV_ID_KEYPAD); // source device id 433 buf.write(DEV_ID_UICC); // destination device id 434 435 // item identifier 436 tag = 0x80 | ComprehensionTlvTag.ITEM_ID.value(); 437 buf.write(tag); 438 buf.write(0x01); // length 439 buf.write(menuId); // menu identifier chosen 440 441 // help request 442 if (helpRequired) { 443 tag = ComprehensionTlvTag.HELP_REQUEST.value(); 444 buf.write(tag); 445 buf.write(0x00); // length 446 } 447 448 byte[] rawData = buf.toByteArray(); 449 450 // write real length 451 int len = rawData.length - 2; // minus (tag + length) 452 rawData[1] = (byte) len; 453 454 String hexString = IccUtils.bytesToHexString(rawData); 455 456 mCmdIf.sendEnvelope(hexString, null); 457 } 458 459 private void eventDownload(int event, int sourceId, int destinationId, 460 byte[] additionalInfo, boolean oneShot) { 461 462 ByteArrayOutputStream buf = new ByteArrayOutputStream(); 463 464 // tag 465 int tag = BerTlv.BER_EVENT_DOWNLOAD_TAG; 466 buf.write(tag); 467 468 // length 469 buf.write(0x00); // place holder, assume length < 128. 470 471 // event list 472 tag = 0x80 | ComprehensionTlvTag.EVENT_LIST.value(); 473 buf.write(tag); 474 buf.write(0x01); // length 475 buf.write(event); // event value 476 477 // device identities 478 tag = 0x80 | ComprehensionTlvTag.DEVICE_IDENTITIES.value(); 479 buf.write(tag); 480 buf.write(0x02); // length 481 buf.write(sourceId); // source device id 482 buf.write(destinationId); // destination device id 483 484 // additional information 485 if (additionalInfo != null) { 486 for (byte b : additionalInfo) { 487 buf.write(b); 488 } 489 } 490 491 byte[] rawData = buf.toByteArray(); 492 493 // write real length 494 int len = rawData.length - 2; // minus (tag + length) 495 rawData[1] = (byte) len; 496 497 String hexString = IccUtils.bytesToHexString(rawData); 498 499 mCmdIf.sendEnvelope(hexString, null); 500 } 501 502 /** 503 * Used for instantiating/updating the Service from the GsmPhone or CdmaPhone constructor. 504 * 505 * @param ci CommandsInterface object 506 * @param ir IccRecords object 507 * @param context phone app context 508 * @param fh Icc file handler 509 * @param ic Icc card 510 * @return The only Service object in the system 511 */ 512 public static CatService getInstance(CommandsInterface ci, IccRecords ir, 513 Context context, IccFileHandler fh, IccCard ic) { 514 synchronized (sInstanceLock) { 515 if (sInstance == null) { 516 if (ci == null || ir == null || context == null || fh == null 517 || ic == null) { 518 return null; 519 } 520 HandlerThread thread = new HandlerThread("Cat Telephony service"); 521 thread.start(); 522 sInstance = new CatService(ci, ir, context, fh, ic); 523 CatLog.d(sInstance, "NEW sInstance"); 524 } else if ((ir != null) && (mIccRecords != ir)) { 525 CatLog.d(sInstance, "Reinitialize the Service with SIMRecords"); 526 mIccRecords = ir; 527 528 // re-Register for SIM ready event. 529 mIccRecords.registerForRecordsLoaded(sInstance, MSG_ID_ICC_RECORDS_LOADED, null); 530 CatLog.d(sInstance, "sr changed reinitialize and return current sInstance"); 531 } else { 532 CatLog.d(sInstance, "Return current sInstance"); 533 } 534 return sInstance; 535 } 536 } 537 538 /** 539 * Used by application to get an AppInterface object. 540 * 541 * @return The only Service object in the system 542 */ 543 public static AppInterface getInstance() { 544 return getInstance(null, null, null, null, null); 545 } 546 547 @Override 548 public void handleMessage(Message msg) { 549 550 switch (msg.what) { 551 case MSG_ID_SESSION_END: 552 case MSG_ID_PROACTIVE_COMMAND: 553 case MSG_ID_EVENT_NOTIFY: 554 case MSG_ID_REFRESH: 555 CatLog.d(this, "ril message arrived"); 556 String data = null; 557 if (msg.obj != null) { 558 AsyncResult ar = (AsyncResult) msg.obj; 559 if (ar != null && ar.result != null) { 560 try { 561 data = (String) ar.result; 562 } catch (ClassCastException e) { 563 break; 564 } 565 } 566 } 567 mMsgDecoder.sendStartDecodingMessageParams(new RilMessage(msg.what, data)); 568 break; 569 case MSG_ID_CALL_SETUP: 570 mMsgDecoder.sendStartDecodingMessageParams(new RilMessage(msg.what, null)); 571 break; 572 case MSG_ID_ICC_RECORDS_LOADED: 573 break; 574 case MSG_ID_RIL_MSG_DECODED: 575 handleRilMsg((RilMessage) msg.obj); 576 break; 577 case MSG_ID_RESPONSE: 578 handleCmdResponse((CatResponseMessage) msg.obj); 579 break; 580 case MSG_ID_SIM_READY: 581 CatLog.d(this, "SIM ready. Reporting STK service running now..."); 582 mCmdIf.reportStkServiceIsRunning(null); 583 break; 584 default: 585 throw new AssertionError("Unrecognized CAT command: " + msg.what); 586 } 587 } 588 589 public synchronized void onCmdResponse(CatResponseMessage resMsg) { 590 if (resMsg == null) { 591 return; 592 } 593 // queue a response message. 594 Message msg = this.obtainMessage(MSG_ID_RESPONSE, resMsg); 595 msg.sendToTarget(); 596 } 597 598 private boolean validateResponse(CatResponseMessage resMsg) { 599 if (mCurrntCmd != null) { 600 return (resMsg.cmdDet.compareTo(mCurrntCmd.mCmdDet)); 601 } 602 return false; 603 } 604 605 private boolean removeMenu(Menu menu) { 606 try { 607 if (menu.items.size() == 1 && menu.items.get(0) == null) { 608 return true; 609 } 610 } catch (NullPointerException e) { 611 CatLog.d(this, "Unable to get Menu's items size"); 612 return true; 613 } 614 return false; 615 } 616 617 private void handleCmdResponse(CatResponseMessage resMsg) { 618 // Make sure the response details match the last valid command. An invalid 619 // response is a one that doesn't have a corresponding proactive command 620 // and sending it can "confuse" the baseband/ril. 621 // One reason for out of order responses can be UI glitches. For example, 622 // if the application launch an activity, and that activity is stored 623 // by the framework inside the history stack. That activity will be 624 // available for relaunch using the latest application dialog 625 // (long press on the home button). Relaunching that activity can send 626 // the same command's result again to the CatService and can cause it to 627 // get out of sync with the SIM. 628 if (!validateResponse(resMsg)) { 629 return; 630 } 631 ResponseData resp = null; 632 boolean helpRequired = false; 633 CommandDetails cmdDet = resMsg.getCmdDetails(); 634 635 switch (resMsg.resCode) { 636 case HELP_INFO_REQUIRED: 637 helpRequired = true; 638 // fall through 639 case OK: 640 case PRFRMD_WITH_PARTIAL_COMPREHENSION: 641 case PRFRMD_WITH_MISSING_INFO: 642 case PRFRMD_WITH_ADDITIONAL_EFS_READ: 643 case PRFRMD_ICON_NOT_DISPLAYED: 644 case PRFRMD_MODIFIED_BY_NAA: 645 case PRFRMD_LIMITED_SERVICE: 646 case PRFRMD_WITH_MODIFICATION: 647 case PRFRMD_NAA_NOT_ACTIVE: 648 case PRFRMD_TONE_NOT_PLAYED: 649 switch (AppInterface.CommandType.fromInt(cmdDet.typeOfCommand)) { 650 case SET_UP_MENU: 651 helpRequired = resMsg.resCode == ResultCode.HELP_INFO_REQUIRED; 652 sendMenuSelection(resMsg.usersMenuSelection, helpRequired); 653 return; 654 case SELECT_ITEM: 655 resp = new SelectItemResponseData(resMsg.usersMenuSelection); 656 break; 657 case GET_INPUT: 658 case GET_INKEY: 659 Input input = mCurrntCmd.geInput(); 660 if (!input.yesNo) { 661 // when help is requested there is no need to send the text 662 // string object. 663 if (!helpRequired) { 664 resp = new GetInkeyInputResponseData(resMsg.usersInput, 665 input.ucs2, input.packed); 666 } 667 } else { 668 resp = new GetInkeyInputResponseData( 669 resMsg.usersYesNoSelection); 670 } 671 break; 672 case DISPLAY_TEXT: 673 case LAUNCH_BROWSER: 674 break; 675 case SET_UP_CALL: 676 mCmdIf.handleCallSetupRequestFromSim(resMsg.usersConfirm, null); 677 // No need to send terminal response for SET UP CALL. The user's 678 // confirmation result is send back using a dedicated ril message 679 // invoked by the CommandInterface call above. 680 mCurrntCmd = null; 681 return; 682 } 683 break; 684 case NO_RESPONSE_FROM_USER: 685 case UICC_SESSION_TERM_BY_USER: 686 case BACKWARD_MOVE_BY_USER: 687 resp = null; 688 break; 689 default: 690 return; 691 } 692 sendTerminalResponse(cmdDet, resMsg.resCode, false, 0, resp); 693 mCurrntCmd = null; 694 } 695 } 696