Merge "SIM toolkit enhancements and bug fixes"

This commit is contained in:
Jean-Baptiste Queru
2010-08-11 09:29:03 -07:00
committed by Android Code Review
5 changed files with 151 additions and 47 deletions

View File

@@ -58,7 +58,8 @@ public interface AppInterface {
SET_UP_EVENT_LIST(0x05),
SET_UP_IDLE_MODE_TEXT(0x28),
SET_UP_MENU(0x25),
SET_UP_CALL(0x10);
SET_UP_CALL(0x10),
PROVIDE_LOCAL_INFORMATION(0x26);
private int mValue;

View File

@@ -22,6 +22,7 @@ import android.os.AsyncResult;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.os.SystemProperties;
import com.android.internal.telephony.IccUtils;
import com.android.internal.telephony.CommandsInterface;
@@ -245,48 +246,46 @@ public class CatService extends Handler implements AppInterface {
CatCmdMessage cmdMsg = new CatCmdMessage(cmdParams);
switch (cmdParams.getCommandType()) {
case SET_UP_MENU:
if (removeMenu(cmdMsg.getMenu())) {
mMenuCmd = null;
} else {
mMenuCmd = cmdMsg;
}
sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0,
null);
break;
case DISPLAY_TEXT:
// when application is not required to respond, send an immediate
// response.
if (!cmdMsg.geTextMessage().responseNeeded) {
sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false,
0, null);
}
break;
case REFRESH:
// ME side only handles refresh commands which meant to remove IDLE
// MODE TEXT.
cmdParams.cmdDet.typeOfCommand = CommandType.SET_UP_IDLE_MODE_TEXT
.value();
break;
case SET_UP_IDLE_MODE_TEXT:
sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false,
0, null);
break;
case LAUNCH_BROWSER:
case SELECT_ITEM:
case GET_INPUT:
case GET_INKEY:
case SEND_DTMF:
case SEND_SMS:
case SEND_SS:
case SEND_USSD:
case PLAY_TONE:
case SET_UP_CALL:
// nothing to do on telephony!
break;
default:
CatLog.d(this, "Unsupported command");
return;
case SET_UP_MENU:
if (removeMenu(cmdMsg.getMenu())) {
mMenuCmd = null;
} else {
mMenuCmd = cmdMsg;
}
sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null);
break;
case DISPLAY_TEXT:
// when application is not required to respond, send an immediate response.
if (!cmdMsg.geTextMessage().responseNeeded) {
sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null);
}
break;
case REFRESH:
// ME side only handles refresh commands which meant to remove IDLE
// MODE TEXT.
cmdParams.cmdDet.typeOfCommand = CommandType.SET_UP_IDLE_MODE_TEXT.value();
break;
case SET_UP_IDLE_MODE_TEXT:
sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null);
break;
case PROVIDE_LOCAL_INFORMATION:
sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null);
return;
case LAUNCH_BROWSER:
case SELECT_ITEM:
case GET_INPUT:
case GET_INKEY:
case SEND_DTMF:
case SEND_SMS:
case SEND_SS:
case SEND_USSD:
case PLAY_TONE:
case SET_UP_CALL:
// nothing to do on telephony!
break;
default:
CatLog.d(this, "Unsupported command");
return;
}
mCurrntCmd = cmdMsg;
Intent intent = new Intent(AppInterface.CAT_CMD_ACTION);
@@ -315,6 +314,11 @@ public class CatService extends Handler implements AppInterface {
}
ByteArrayOutputStream buf = new ByteArrayOutputStream();
Input cmdInput = null;
if (mCurrntCmd != null) {
cmdInput = mCurrntCmd.geInput();
}
// command details
int tag = ComprehensionTlvTag.COMMAND_DETAILS.value();
if (cmdDet.compRequired) {
@@ -327,7 +331,13 @@ public class CatService extends Handler implements AppInterface {
buf.write(cmdDet.commandQualifier);
// device identities
tag = 0x80 | ComprehensionTlvTag.DEVICE_IDENTITIES.value();
// 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
@@ -348,6 +358,8 @@ public class CatService extends Handler implements AppInterface {
// Fill optional data for each corresponding command
if (resp != null) {
resp.format(buf);
} else {
encodeOptionalTags(cmdDet, resultCode, cmdInput, buf);
}
byte[] rawData = buf.toByteArray();
@@ -359,6 +371,52 @@ public class CatService extends Handler implements AppInterface {
mCmdIf.sendTerminalResponse(hexString, null);
}
private void encodeOptionalTags(CommandDetails cmdDet,
ResultCode resultCode, Input cmdInput, ByteArrayOutputStream buf) {
switch (AppInterface.CommandType.fromInt(cmdDet.typeOfCommand)) {
case GET_INKEY:
// ETSI TS 102 384,27.22.4.2.8.4.2.
// If it is a response for GET_INKEY command and the response timeout
// occured, then add DURATION TLV for variable timeout case.
if ((resultCode.value() == ResultCode.NO_RESPONSE_FROM_USER.value()) &&
(cmdInput != null) && (cmdInput.duration != null)) {
getInKeyResponse(buf, cmdInput);
}
break;
case PROVIDE_LOCAL_INFORMATION:
if ((cmdDet.commandQualifier == CommandParamsFactory.LANGUAGE_SETTING) &&
(resultCode.value() == ResultCode.OK.value())) {
getPliResponse(buf);
}
break;
default:
CatLog.d(this, "encodeOptionalTags() Unsupported Cmd:" + cmdDet.typeOfCommand);
break;
}
}
private void getInKeyResponse(ByteArrayOutputStream buf, Input cmdInput) {
int tag = ComprehensionTlvTag.DURATION.value();
buf.write(tag);
buf.write(0x02); // length
buf.write(cmdInput.duration.timeUnit.SECOND.value()); // Time (Unit,Seconds)
buf.write(cmdInput.duration.timeInterval); // Time Duration
}
private void getPliResponse(ByteArrayOutputStream buf) {
// Locale Language Setting
String lang = SystemProperties.get("persist.sys.language");
if (lang != null) {
// tag
int tag = ComprehensionTlvTag.LANGUAGE.value();
buf.write(tag);
ResponseData.writeLength(buf, lang.length());
buf.write(lang.getBytes(), 0, lang.length());
}
}
private void sendMenuSelection(int menuId, boolean helpRequired) {

View File

@@ -52,6 +52,9 @@ class CommandParamsFactory extends Handler {
static final int REFRESH_NAA_INIT = 0x03;
static final int REFRESH_UICC_RESET = 0x04;
// Command Qualifier values for PLI command
static final int LANGUAGE_SETTING = 0x04;
static synchronized CommandParamsFactory getInstance(RilMessageDecoder caller,
IccFileHandler fh) {
if (sInstance != null) {
@@ -112,7 +115,10 @@ class CommandParamsFactory extends Handler {
AppInterface.CommandType cmdType = AppInterface.CommandType
.fromInt(cmdDet.typeOfCommand);
if (cmdType == null) {
sendCmdParams(ResultCode.CMD_TYPE_NOT_UNDERSTOOD);
// This PROACTIVE COMMAND is presently not handled. Hence set
// result code as BEYOND_TERMINAL_CAPABILITY in TR.
mCmdParams = new CommandParams(cmdDet);
sendCmdParams(ResultCode.BEYOND_TERMINAL_CAPABILITY);
return;
}
@@ -155,10 +161,13 @@ class CommandParamsFactory extends Handler {
case PLAY_TONE:
cmdPending = processPlayTone(cmdDet, ctlvs);
break;
case PROVIDE_LOCAL_INFORMATION:
cmdPending = processProvideLocalInfo(cmdDet, ctlvs);
break;
default:
// unsupported proactive commands
mCmdParams = new CommandParams(cmdDet);
sendCmdParams(ResultCode.CMD_TYPE_NOT_UNDERSTOOD);
sendCmdParams(ResultCode.BEYOND_TERMINAL_CAPABILITY);
return;
}
} catch (ResultException e) {
@@ -380,6 +389,12 @@ class CommandParamsFactory extends Handler {
iconId = ValueParser.retrieveIconId(ctlv);
}
// parse duration
ctlv = searchForTag(ComprehensionTlvTag.DURATION, ctlvs);
if (ctlv != null) {
input.duration = ValueParser.retrieveDuration(ctlv);
}
input.minLen = 1;
input.maxLen = 1;
@@ -863,4 +878,20 @@ class CommandParamsFactory extends Handler {
}
return false;
}
private boolean processProvideLocalInfo(CommandDetails cmdDet, List<ComprehensionTlv> ctlvs)
throws ResultException {
CatLog.d(this, "process ProvideLocalInfo");
switch (cmdDet.commandQualifier) {
case LANGUAGE_SETTING:
CatLog.d(this, "PLI [LANGUAGE_SETTING]");
mCmdParams = new CommandParams(cmdDet);
break;
default:
CatLog.d(this, "PLI[" + cmdDet.commandQualifier + "] Command Not Supported");
mCmdParams = new CommandParams(cmdDet);
throw new ResultException(ResultCode.BEYOND_TERMINAL_CAPABILITY);
}
return false;
}
}

View File

@@ -36,6 +36,7 @@ public class Input implements Parcelable {
public boolean echo;
public boolean yesNo;
public boolean helpAvailable;
public Duration duration;
Input() {
text = "";
@@ -49,6 +50,7 @@ public class Input implements Parcelable {
echo = false;
yesNo = false;
helpAvailable = false;
duration = null;
}
private Input(Parcel in) {
@@ -63,6 +65,7 @@ public class Input implements Parcelable {
echo = in.readInt() == 1 ? true : false;
yesNo = in.readInt() == 1 ? true : false;
helpAvailable = in.readInt() == 1 ? true : false;
duration = in.readParcelable(null);
}
public int describeContents() {
@@ -81,6 +84,7 @@ public class Input implements Parcelable {
dest.writeInt(echo ? 1 : 0);
dest.writeInt(yesNo ? 1 : 0);
dest.writeInt(helpAvailable ? 1 : 0);
dest.writeParcelable(duration, 0);
}
public static final Parcelable.Creator<Input> CREATOR = new Parcelable.Creator<Input>() {

View File

@@ -28,6 +28,16 @@ abstract class ResponseData {
* the ByteArrayOutputStream object.
*/
public abstract void format(ByteArrayOutputStream buf);
public static void writeLength(ByteArrayOutputStream buf, int length) {
// As per ETSI 102.220 Sec7.1.2, if the total length is greater
// than 0x7F, it should be coded in two bytes and the first byte
// should be 0x81.
if (length > 0x7F) {
buf.write(0x81);
}
buf.write(length);
}
}
class SelectItemResponseData extends ResponseData {
@@ -120,7 +130,7 @@ class GetInkeyInputResponseData extends ResponseData {
}
// length - one more for data coding scheme.
buf.write(data.length + 1);
writeLength(buf, data.length + 1);
// data coding scheme
if (mIsUcs2) {