private void sendTerminalResponse( CommandDetails cmdDet, ResultCode resultCode, boolean includeAdditionalInfo, int additionalInfo, ResponseData resp) { if (cmdDet == null) { return; } ByteArrayOutputStream buf = new ByteArrayOutputStream(); Input cmdInput = null; if (mCurrntCmd != null) { cmdInput = mCurrntCmd.geInput(); } // command details int tag = ComprehensionTlvTag.COMMAND_DETAILS.value(); if (cmdDet.compRequired) { tag |= 0x80; } buf.write(tag); buf.write(0x03); // length buf.write(cmdDet.commandNumber); buf.write(cmdDet.typeOfCommand); buf.write(cmdDet.commandQualifier); // device identities // According to TS102.223/TS31.111 section 6.8 Structure of // TERMINAL RESPONSE, "For all SIMPLE-TLV objects with Min=N, // the ME should set the CR(comprehension required) flag to // comprehension not required.(CR=0)" // Since DEVICE_IDENTITIES and DURATION TLVs have Min=N, // the CR flag is not set. tag = ComprehensionTlvTag.DEVICE_IDENTITIES.value(); buf.write(tag); buf.write(0x02); // length buf.write(DEV_ID_TERMINAL); // source device id buf.write(DEV_ID_UICC); // destination device id // result tag = ComprehensionTlvTag.RESULT.value(); if (cmdDet.compRequired) { tag |= 0x80; } buf.write(tag); int length = includeAdditionalInfo ? 2 : 1; buf.write(length); buf.write(resultCode.value()); // additional info if (includeAdditionalInfo) { buf.write(additionalInfo); } // Fill optional data for each corresponding command if (resp != null) { resp.format(buf); } else { encodeOptionalTags(cmdDet, resultCode, cmdInput, buf); } byte[] rawData = buf.toByteArray(); String hexString = IccUtils.bytesToHexString(rawData); if (DBG) { CatLog.d(this, "TERMINAL RESPONSE: " + hexString); } mCmdIf.sendTerminalResponse(hexString, null); }
private void handleCmdResponse(CatResponseMessage resMsg) { // Make sure the response details match the last valid command. An invalid // response is a one that doesn't have a corresponding proactive command // and sending it can "confuse" the baseband/ril. // One reason for out of order responses can be UI glitches. For example, // if the application launch an activity, and that activity is stored // by the framework inside the history stack. That activity will be // available for relaunch using the latest application dialog // (long press on the home button). Relaunching that activity can send // the same command's result again to the CatService and can cause it to // get out of sync with the SIM. This can happen in case of // non-interactive type Setup Event List and SETUP_MENU proactive commands. // Stk framework would have already sent Terminal Response to Setup Event // List and SETUP_MENU proactive commands. After sometime Stk app will send // Envelope Command/Event Download. In which case, the response details doesn't // match with last valid command (which are not related). // However, we should allow Stk framework to send the message to ICC. if (!validateResponse(resMsg)) { return; } ResponseData resp = null; boolean helpRequired = false; CommandDetails cmdDet = resMsg.getCmdDetails(); AppInterface.CommandType type = AppInterface.CommandType.fromInt(cmdDet.typeOfCommand); switch (resMsg.mResCode) { case HELP_INFO_REQUIRED: helpRequired = true; // fall through case OK: case PRFRMD_WITH_PARTIAL_COMPREHENSION: case PRFRMD_WITH_MISSING_INFO: case PRFRMD_WITH_ADDITIONAL_EFS_READ: case PRFRMD_ICON_NOT_DISPLAYED: case PRFRMD_MODIFIED_BY_NAA: case PRFRMD_LIMITED_SERVICE: case PRFRMD_WITH_MODIFICATION: case PRFRMD_NAA_NOT_ACTIVE: case PRFRMD_TONE_NOT_PLAYED: case LAUNCH_BROWSER_ERROR: case TERMINAL_CRNTLY_UNABLE_TO_PROCESS: switch (type) { case SET_UP_MENU: helpRequired = resMsg.mResCode == ResultCode.HELP_INFO_REQUIRED; sendMenuSelection(resMsg.mUsersMenuSelection, helpRequired); return; case SELECT_ITEM: resp = new SelectItemResponseData(resMsg.mUsersMenuSelection); break; case GET_INPUT: case GET_INKEY: Input input = mCurrntCmd.geInput(); if (!input.yesNo) { // when help is requested there is no need to send the text // string object. if (!helpRequired) { resp = new GetInkeyInputResponseData(resMsg.mUsersInput, input.ucs2, input.packed); } } else { resp = new GetInkeyInputResponseData(resMsg.mUsersYesNoSelection); } break; case DISPLAY_TEXT: if (resMsg.mResCode == ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS) { // For screenbusy case there will be addtional information in the terminal // response. And the value of the additional information byte is 0x01. resMsg.setAdditionalInfo(0x01); } else { resMsg.mIncludeAdditionalInfo = false; resMsg.mAdditionalInfo = 0; } break; case LAUNCH_BROWSER: break; // 3GPP TS.102.223: Open Channel alpha confirmation should not send TR case OPEN_CHANNEL: case SET_UP_CALL: mCmdIf.handleCallSetupRequestFromSim(resMsg.mUsersConfirm, null); // No need to send terminal response for SET UP CALL. The user's // confirmation result is send back using a dedicated ril message // invoked by the CommandInterface call above. mCurrntCmd = null; return; case SET_UP_EVENT_LIST: if (IDLE_SCREEN_AVAILABLE_EVENT == resMsg.mEventValue) { eventDownload( resMsg.mEventValue, DEV_ID_DISPLAY, DEV_ID_UICC, resMsg.mAddedInfo, false); } else { eventDownload( resMsg.mEventValue, DEV_ID_TERMINAL, DEV_ID_UICC, resMsg.mAddedInfo, false); } // No need to send the terminal response after event download. return; default: break; } break; case BACKWARD_MOVE_BY_USER: case USER_NOT_ACCEPT: // if the user dismissed the alert dialog for a // setup call/open channel, consider that as the user // rejecting the call. Use dedicated API for this, rather than // sending a terminal response. if (type == CommandType.SET_UP_CALL || type == CommandType.OPEN_CHANNEL) { mCmdIf.handleCallSetupRequestFromSim(false, null); mCurrntCmd = null; return; } else { resp = null; } break; case NO_RESPONSE_FROM_USER: // No need to send terminal response for SET UP CALL on user timeout. if (type == CommandType.SET_UP_CALL) { mCurrntCmd = null; return; } case UICC_SESSION_TERM_BY_USER: resp = null; break; default: return; } sendTerminalResponse( cmdDet, resMsg.mResCode, resMsg.mIncludeAdditionalInfo, resMsg.mAdditionalInfo, resp); mCurrntCmd = null; }
private void handleCmdResponse(CatResponseMessage resMsg) { // Make sure the response details match the last valid command. An invalid // response is a one that doesn't have a corresponding proactive command // and sending it can "confuse" the baseband/ril. // One reason for out of order responses can be UI glitches. For example, // if the application launch an activity, and that activity is stored // by the framework inside the history stack. That activity will be // available for relaunch using the latest application dialog // (long press on the home button). Relaunching that activity can send // the same command's result again to the CatService and can cause it to // get out of sync with the SIM. if (!validateResponse(resMsg)) { return; } ResponseData resp = null; boolean helpRequired = false; CommandDetails cmdDet = resMsg.getCmdDetails(); AppInterface.CommandType type = AppInterface.CommandType.fromInt(cmdDet.typeOfCommand); switch (resMsg.resCode) { case HELP_INFO_REQUIRED: helpRequired = true; // fall through case OK: case PRFRMD_WITH_PARTIAL_COMPREHENSION: case PRFRMD_WITH_MISSING_INFO: case PRFRMD_WITH_ADDITIONAL_EFS_READ: case PRFRMD_ICON_NOT_DISPLAYED: case PRFRMD_MODIFIED_BY_NAA: case PRFRMD_LIMITED_SERVICE: case PRFRMD_WITH_MODIFICATION: case PRFRMD_NAA_NOT_ACTIVE: case PRFRMD_TONE_NOT_PLAYED: case TERMINAL_CRNTLY_UNABLE_TO_PROCESS: switch (type) { case SET_UP_MENU: helpRequired = resMsg.resCode == ResultCode.HELP_INFO_REQUIRED; sendMenuSelection(resMsg.usersMenuSelection, helpRequired); return; case SELECT_ITEM: resp = new SelectItemResponseData(resMsg.usersMenuSelection); break; case GET_INPUT: case GET_INKEY: Input input = mCurrntCmd.geInput(); if (!input.yesNo) { // when help is requested there is no need to send the text // string object. if (!helpRequired) { resp = new GetInkeyInputResponseData(resMsg.usersInput, input.ucs2, input.packed); } } else { resp = new GetInkeyInputResponseData(resMsg.usersYesNoSelection); } break; case DISPLAY_TEXT: case LAUNCH_BROWSER: break; case SET_UP_CALL: mCmdIf.handleCallSetupRequestFromSim(resMsg.usersConfirm, null); // No need to send terminal response for SET UP CALL. The user's // confirmation result is send back using a dedicated ril message // invoked by the CommandInterface call above. mCurrntCmd = null; return; } break; case BACKWARD_MOVE_BY_USER: case USER_NOT_ACCEPT: // if the user dismissed the alert dialog for a // setup call/open channel, consider that as the user // rejecting the call. Use dedicated API for this, rather than // sending a terminal response. if (type == CommandType.SET_UP_CALL || type == CommandType.OPEN_CHANNEL) { mCmdIf.handleCallSetupRequestFromSim(false, null); mCurrntCmd = null; return; } else { resp = null; } break; case NO_RESPONSE_FROM_USER: case UICC_SESSION_TERM_BY_USER: resp = null; break; default: return; } sendTerminalResponse( cmdDet, resMsg.resCode, resMsg.includeAdditionalInfo, resMsg.additionalInfo, resp); mCurrntCmd = null; }