blob: 7cc94636ca237b3d6447460e4f489b2a0181c0eb [file] [log] [blame]
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.telephony.cat;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.uicc.IccFileHandler;
import java.util.Iterator;
import java.util.List;
import static com.android.internal.telephony.cat.CatCmdMessage.
SetupEventListConstants.USER_ACTIVITY_EVENT;
import static com.android.internal.telephony.cat.CatCmdMessage.
SetupEventListConstants.IDLE_SCREEN_AVAILABLE_EVENT;
import static com.android.internal.telephony.cat.CatCmdMessage.
SetupEventListConstants.LANGUAGE_SELECTION_EVENT;
import static com.android.internal.telephony.cat.CatCmdMessage.
SetupEventListConstants.BROWSER_TERMINATION_EVENT;
import static com.android.internal.telephony.cat.CatCmdMessage.
SetupEventListConstants.BROWSING_STATUS_EVENT;
/**
* Factory class, used for decoding raw byte arrays, received from baseband,
* into a CommandParams object.
*
*/
class CommandParamsFactory extends Handler {
private static CommandParamsFactory sInstance = null;
private IconLoader mIconLoader;
private CommandParams mCmdParams = null;
private int mIconLoadState = LOAD_NO_ICON;
private RilMessageDecoder mCaller = null;
private boolean mloadIcon = false;
// constants
static final int MSG_ID_LOAD_ICON_DONE = 1;
// loading icons state parameters.
static final int LOAD_NO_ICON = 0;
static final int LOAD_SINGLE_ICON = 1;
static final int LOAD_MULTI_ICONS = 2;
// Command Qualifier values for refresh command
static final int REFRESH_NAA_INIT_AND_FULL_FILE_CHANGE = 0x00;
static final int REFRESH_NAA_INIT_AND_FILE_CHANGE = 0x02;
static final int REFRESH_NAA_INIT = 0x03;
static final int REFRESH_UICC_RESET = 0x04;
// Command Qualifier values for PLI command
static final int DTTZ_SETTING = 0x03;
static final int LANGUAGE_SETTING = 0x04;
// As per TS 102.223 Annex C, Structure of CAT communications,
// the APDU length can be max 255 bytes. This leaves only 239 bytes for user
// input string. CMD details TLV + Device IDs TLV + Result TLV + Other
// details of TextString TLV not including user input take 16 bytes.
//
// If UCS2 encoding is used, maximum 118 UCS2 chars can be encoded in 238 bytes.
// Each UCS2 char takes 2 bytes. Byte Order Mask(BOM), 0xFEFF takes 2 bytes.
//
// If GSM 7 bit default(use 8 bits to represent a 7 bit char) format is used,
// maximum 239 chars can be encoded in 239 bytes since each char takes 1 byte.
//
// No issues for GSM 7 bit packed format encoding.
private static final int MAX_GSM7_DEFAULT_CHARS = 239;
private static final int MAX_UCS2_CHARS = 118;
static synchronized CommandParamsFactory getInstance(RilMessageDecoder caller,
IccFileHandler fh) {
if (sInstance != null) {
return sInstance;
}
if (fh != null) {
return new CommandParamsFactory(caller, fh);
}
return null;
}
private CommandParamsFactory(RilMessageDecoder caller, IccFileHandler fh) {
mCaller = caller;
mIconLoader = IconLoader.getInstance(this, fh);
}
private CommandDetails processCommandDetails(List<ComprehensionTlv> ctlvs) {
CommandDetails cmdDet = null;
if (ctlvs != null) {
// Search for the Command Details object.
ComprehensionTlv ctlvCmdDet = searchForTag(
ComprehensionTlvTag.COMMAND_DETAILS, ctlvs);
if (ctlvCmdDet != null) {
try {
cmdDet = ValueParser.retrieveCommandDetails(ctlvCmdDet);
} catch (ResultException e) {
CatLog.d(this,
"processCommandDetails: Failed to procees command details e=" + e);
}
}
}
return cmdDet;
}
void make(BerTlv berTlv) {
if (berTlv == null) {
return;
}
// reset global state parameters.
mCmdParams = null;
mIconLoadState = LOAD_NO_ICON;
// only proactive command messages are processed.
if (berTlv.getTag() != BerTlv.BER_PROACTIVE_COMMAND_TAG) {
sendCmdParams(ResultCode.CMD_TYPE_NOT_UNDERSTOOD);
return;
}
boolean cmdPending = false;
List<ComprehensionTlv> ctlvs = berTlv.getComprehensionTlvs();
// process command dtails from the tlv list.
CommandDetails cmdDet = processCommandDetails(ctlvs);
if (cmdDet == null) {
sendCmdParams(ResultCode.CMD_TYPE_NOT_UNDERSTOOD);
return;
}
// extract command type enumeration from the raw value stored inside
// the Command Details object.
AppInterface.CommandType cmdType = AppInterface.CommandType
.fromInt(cmdDet.typeOfCommand);
if (cmdType == null) {
// 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;
}
// proactive command length is incorrect.
if (!berTlv.isLengthValid()) {
mCmdParams = new CommandParams(cmdDet);
sendCmdParams(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
return;
}
try {
switch (cmdType) {
case SET_UP_MENU:
cmdPending = processSelectItem(cmdDet, ctlvs);
break;
case SELECT_ITEM:
cmdPending = processSelectItem(cmdDet, ctlvs);
break;
case DISPLAY_TEXT:
cmdPending = processDisplayText(cmdDet, ctlvs);
break;
case SET_UP_IDLE_MODE_TEXT:
cmdPending = processSetUpIdleModeText(cmdDet, ctlvs);
break;
case GET_INKEY:
cmdPending = processGetInkey(cmdDet, ctlvs);
break;
case GET_INPUT:
cmdPending = processGetInput(cmdDet, ctlvs);
break;
case SEND_DTMF:
case SEND_SMS:
case SEND_SS:
case SEND_USSD:
cmdPending = processEventNotify(cmdDet, ctlvs);
break;
case GET_CHANNEL_STATUS:
case SET_UP_CALL:
cmdPending = processSetupCall(cmdDet, ctlvs);
break;
case REFRESH:
processRefresh(cmdDet, ctlvs);
cmdPending = false;
break;
case LAUNCH_BROWSER:
cmdPending = processLaunchBrowser(cmdDet, ctlvs);
break;
case PLAY_TONE:
cmdPending = processPlayTone(cmdDet, ctlvs);
break;
case SET_UP_EVENT_LIST:
cmdPending = processSetUpEventList(cmdDet, ctlvs);
break;
case PROVIDE_LOCAL_INFORMATION:
cmdPending = processProvideLocalInfo(cmdDet, ctlvs);
break;
case OPEN_CHANNEL:
case CLOSE_CHANNEL:
case RECEIVE_DATA:
case SEND_DATA:
cmdPending = processBIPClient(cmdDet, ctlvs);
break;
default:
// unsupported proactive commands
mCmdParams = new CommandParams(cmdDet);
sendCmdParams(ResultCode.BEYOND_TERMINAL_CAPABILITY);
return;
}
} catch (ResultException e) {
CatLog.d(this, "make: caught ResultException e=" + e);
mCmdParams = new CommandParams(cmdDet);
sendCmdParams(e.result());
return;
}
if (!cmdPending) {
sendCmdParams(ResultCode.OK);
}
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ID_LOAD_ICON_DONE:
sendCmdParams(setIcons(msg.obj));
break;
}
}
private ResultCode setIcons(Object data) {
Bitmap[] icons = null;
int iconIndex = 0;
if (data == null) {
CatLog.d(this, "Optional Icon data is NULL");
mCmdParams.mLoadIconFailed = true;
mloadIcon = false;
/** In case of icon load fail consider the
** received proactive command as valid (sending RESULT OK) as
** The result code, 'PRFRMD_ICON_NOT_DISPLAYED' will be added in the
** terminal response by CatService/StkAppService if needed based on
** the value of mLoadIconFailed.
*/
return ResultCode.OK;
}
switch(mIconLoadState) {
case LOAD_SINGLE_ICON:
mCmdParams.setIcon((Bitmap) data);
break;
case LOAD_MULTI_ICONS:
icons = (Bitmap[]) data;
// set each item icon.
for (Bitmap icon : icons) {
mCmdParams.setIcon(icon);
if (icon == null && mloadIcon) {
CatLog.d(this, "Optional Icon data is NULL while loading multi icons");
mCmdParams.mLoadIconFailed = true;
}
}
break;
}
return ResultCode.OK;
}
private void sendCmdParams(ResultCode resCode) {
mCaller.sendMsgParamsDecoded(resCode, mCmdParams);
}
/**
* Search for a COMPREHENSION-TLV object with the given tag from a list
*
* @param tag A tag to search for
* @param ctlvs List of ComprehensionTlv objects used to search in
*
* @return A ComprehensionTlv object that has the tag value of {@code tag}.
* If no object is found with the tag, null is returned.
*/
private ComprehensionTlv searchForTag(ComprehensionTlvTag tag,
List<ComprehensionTlv> ctlvs) {
Iterator<ComprehensionTlv> iter = ctlvs.iterator();
return searchForNextTag(tag, iter);
}
/**
* Search for the next COMPREHENSION-TLV object with the given tag from a
* list iterated by {@code iter}. {@code iter} points to the object next to
* the found object when this method returns. Used for searching the same
* list for similar tags, usually item id.
*
* @param tag A tag to search for
* @param iter Iterator for ComprehensionTlv objects used for search
*
* @return A ComprehensionTlv object that has the tag value of {@code tag}.
* If no object is found with the tag, null is returned.
*/
private ComprehensionTlv searchForNextTag(ComprehensionTlvTag tag,
Iterator<ComprehensionTlv> iter) {
int tagValue = tag.value();
while (iter.hasNext()) {
ComprehensionTlv ctlv = iter.next();
if (ctlv.getTag() == tagValue) {
return ctlv;
}
}
return null;
}
/**
* Processes DISPLAY_TEXT proactive command from the SIM card.
*
* @param cmdDet Command Details container object.
* @param ctlvs List of ComprehensionTlv objects following Command Details
* object and Device Identities object within the proactive command
* @return true if the command is processing is pending and additional
* asynchronous processing is required.
* @throws ResultException
*/
private boolean processDisplayText(CommandDetails cmdDet,
List<ComprehensionTlv> ctlvs)
throws ResultException {
CatLog.d(this, "process DisplayText");
TextMessage textMsg = new TextMessage();
IconId iconId = null;
ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TEXT_STRING,
ctlvs);
if (ctlv != null) {
textMsg.text = ValueParser.retrieveTextString(ctlv);
}
// If the tlv object doesn't exist or the it is a null object reply
// with command not understood.
if (textMsg.text == null) {
throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
}
ctlv = searchForTag(ComprehensionTlvTag.IMMEDIATE_RESPONSE, ctlvs);
if (ctlv != null) {
textMsg.responseNeeded = false;
}
// parse icon identifier
ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
if (ctlv != null) {
iconId = ValueParser.retrieveIconId(ctlv);
textMsg.iconSelfExplanatory = iconId.selfExplanatory;
}
// parse tone duration
ctlv = searchForTag(ComprehensionTlvTag.DURATION, ctlvs);
if (ctlv != null) {
textMsg.duration = ValueParser.retrieveDuration(ctlv);
}
// Parse command qualifier parameters.
textMsg.isHighPriority = (cmdDet.commandQualifier & 0x01) != 0;
textMsg.userClear = (cmdDet.commandQualifier & 0x80) != 0;
mCmdParams = new DisplayTextParams(cmdDet, textMsg);
if (iconId != null) {
mloadIcon = true;
mIconLoadState = LOAD_SINGLE_ICON;
mIconLoader.loadIcon(iconId.recordNumber, this
.obtainMessage(MSG_ID_LOAD_ICON_DONE));
return true;
}
return false;
}
/**
* Processes SET_UP_IDLE_MODE_TEXT proactive command from the SIM card.
*
* @param cmdDet Command Details container object.
* @param ctlvs List of ComprehensionTlv objects following Command Details
* object and Device Identities object within the proactive command
* @return true if the command is processing is pending and additional
* asynchronous processing is required.
* @throws ResultException
*/
private boolean processSetUpIdleModeText(CommandDetails cmdDet,
List<ComprehensionTlv> ctlvs) throws ResultException {
CatLog.d(this, "process SetUpIdleModeText");
TextMessage textMsg = new TextMessage();
IconId iconId = null;
ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TEXT_STRING,
ctlvs);
if (ctlv != null) {
textMsg.text = ValueParser.retrieveTextString(ctlv);
}
ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
if (ctlv != null) {
iconId = ValueParser.retrieveIconId(ctlv);
textMsg.iconSelfExplanatory = iconId.selfExplanatory;
}
/*
* If the tlv object doesn't contain text and the icon is not self
* explanatory then reply with command not understood.
*/
if (textMsg.text == null && iconId != null && !textMsg.iconSelfExplanatory) {
throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
}
mCmdParams = new DisplayTextParams(cmdDet, textMsg);
if (iconId != null) {
mloadIcon = true;
mIconLoadState = LOAD_SINGLE_ICON;
mIconLoader.loadIcon(iconId.recordNumber, this
.obtainMessage(MSG_ID_LOAD_ICON_DONE));
return true;
}
return false;
}
/**
* Processes GET_INKEY proactive command from the SIM card.
*
* @param cmdDet Command Details container object.
* @param ctlvs List of ComprehensionTlv objects following Command Details
* object and Device Identities object within the proactive command
* @return true if the command is processing is pending and additional
* asynchronous processing is required.
* @throws ResultException
*/
private boolean processGetInkey(CommandDetails cmdDet,
List<ComprehensionTlv> ctlvs) throws ResultException {
CatLog.d(this, "process GetInkey");
Input input = new Input();
IconId iconId = null;
ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TEXT_STRING,
ctlvs);
if (ctlv != null) {
input.text = ValueParser.retrieveTextString(ctlv);
} else {
throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
}
// parse icon identifier
ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
if (ctlv != null) {
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;
input.digitOnly = (cmdDet.commandQualifier & 0x01) == 0;
input.ucs2 = (cmdDet.commandQualifier & 0x02) != 0;
input.yesNo = (cmdDet.commandQualifier & 0x04) != 0;
input.helpAvailable = (cmdDet.commandQualifier & 0x80) != 0;
input.echo = true;
mCmdParams = new GetInputParams(cmdDet, input);
if (iconId != null) {
mloadIcon = true;
mIconLoadState = LOAD_SINGLE_ICON;
mIconLoader.loadIcon(iconId.recordNumber, this
.obtainMessage(MSG_ID_LOAD_ICON_DONE));
return true;
}
return false;
}
/**
* Processes GET_INPUT proactive command from the SIM card.
*
* @param cmdDet Command Details container object.
* @param ctlvs List of ComprehensionTlv objects following Command Details
* object and Device Identities object within the proactive command
* @return true if the command is processing is pending and additional
* asynchronous processing is required.
* @throws ResultException
*/
private boolean processGetInput(CommandDetails cmdDet,
List<ComprehensionTlv> ctlvs) throws ResultException {
CatLog.d(this, "process GetInput");
Input input = new Input();
IconId iconId = null;
ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TEXT_STRING,
ctlvs);
if (ctlv != null) {
input.text = ValueParser.retrieveTextString(ctlv);
} else {
throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
}
ctlv = searchForTag(ComprehensionTlvTag.RESPONSE_LENGTH, ctlvs);
if (ctlv != null) {
try {
byte[] rawValue = ctlv.getRawValue();
int valueIndex = ctlv.getValueIndex();
input.minLen = rawValue[valueIndex] & 0xff;
input.maxLen = rawValue[valueIndex + 1] & 0xff;
} catch (IndexOutOfBoundsException e) {
throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
}
} else {
throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
}
ctlv = searchForTag(ComprehensionTlvTag.DEFAULT_TEXT, ctlvs);
if (ctlv != null) {
input.defaultText = ValueParser.retrieveTextString(ctlv);
}
// parse icon identifier
ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
if (ctlv != null) {
iconId = ValueParser.retrieveIconId(ctlv);
}
input.digitOnly = (cmdDet.commandQualifier & 0x01) == 0;
input.ucs2 = (cmdDet.commandQualifier & 0x02) != 0;
input.echo = (cmdDet.commandQualifier & 0x04) == 0;
input.packed = (cmdDet.commandQualifier & 0x08) != 0;
input.helpAvailable = (cmdDet.commandQualifier & 0x80) != 0;
// Truncate the maxLen if it exceeds the max number of chars that can
// be encoded. Limit depends on DCS in Command Qualifier.
if (input.ucs2 && input.maxLen > MAX_UCS2_CHARS) {
CatLog.d(this, "UCS2: received maxLen = " + input.maxLen +
", truncating to " + MAX_UCS2_CHARS);
input.maxLen = MAX_UCS2_CHARS;
} else if (!input.packed && input.maxLen > MAX_GSM7_DEFAULT_CHARS) {
CatLog.d(this, "GSM 7Bit Default: received maxLen = " + input.maxLen +
", truncating to " + MAX_GSM7_DEFAULT_CHARS);
input.maxLen = MAX_GSM7_DEFAULT_CHARS;
}
mCmdParams = new GetInputParams(cmdDet, input);
if (iconId != null) {
mloadIcon = true;
mIconLoadState = LOAD_SINGLE_ICON;
mIconLoader.loadIcon(iconId.recordNumber, this
.obtainMessage(MSG_ID_LOAD_ICON_DONE));
return true;
}
return false;
}
/**
* Processes REFRESH proactive command from the SIM card.
*
* @param cmdDet Command Details container object.
* @param ctlvs List of ComprehensionTlv objects following Command Details
* object and Device Identities object within the proactive command
*/
private boolean processRefresh(CommandDetails cmdDet,
List<ComprehensionTlv> ctlvs) {
CatLog.d(this, "process Refresh");
// REFRESH proactive command is rerouted by the baseband and handled by
// the telephony layer. IDLE TEXT should be removed for a REFRESH command
// with "initialization" or "reset"
switch (cmdDet.commandQualifier) {
case REFRESH_NAA_INIT_AND_FULL_FILE_CHANGE:
case REFRESH_NAA_INIT_AND_FILE_CHANGE:
case REFRESH_NAA_INIT:
case REFRESH_UICC_RESET:
mCmdParams = new DisplayTextParams(cmdDet, null);
break;
}
return false;
}
/**
* Processes SELECT_ITEM proactive command from the SIM card.
*
* @param cmdDet Command Details container object.
* @param ctlvs List of ComprehensionTlv objects following Command Details
* object and Device Identities object within the proactive command
* @return true if the command is processing is pending and additional
* asynchronous processing is required.
* @throws ResultException
*/
private boolean processSelectItem(CommandDetails cmdDet,
List<ComprehensionTlv> ctlvs) throws ResultException {
CatLog.d(this, "process SelectItem");
Menu menu = new Menu();
IconId titleIconId = null;
ItemsIconId itemsIconId = null;
Iterator<ComprehensionTlv> iter = ctlvs.iterator();
AppInterface.CommandType cmdType = AppInterface.CommandType
.fromInt(cmdDet.typeOfCommand);
ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID,
ctlvs);
if (ctlv != null) {
menu.title = ValueParser.retrieveAlphaId(ctlv);
} else if (cmdType == AppInterface.CommandType.SET_UP_MENU) {
// According to spec ETSI TS 102 223 section 6.10.3, the
// Alpha ID is mandatory (and also part of minimum set of
// elements required) for SET_UP_MENU. If it is not received
// by ME, then ME should respond with "error: missing minimum
// information" and not "command performed successfully".
throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
}
while (true) {
ctlv = searchForNextTag(ComprehensionTlvTag.ITEM, iter);
if (ctlv != null) {
menu.items.add(ValueParser.retrieveItem(ctlv));
} else {
break;
}
}
// We must have at least one menu item.
if (menu.items.size() == 0) {
throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
}
ctlv = searchForTag(ComprehensionTlvTag.ITEM_ID, ctlvs);
if (ctlv != null) {
// CAT items are listed 1...n while list start at 0, need to
// subtract one.
menu.defaultItem = ValueParser.retrieveItemId(ctlv) - 1;
}
ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
if (ctlv != null) {
mIconLoadState = LOAD_SINGLE_ICON;
titleIconId = ValueParser.retrieveIconId(ctlv);
menu.titleIconSelfExplanatory = titleIconId.selfExplanatory;
}
ctlv = searchForTag(ComprehensionTlvTag.ITEM_ICON_ID_LIST, ctlvs);
if (ctlv != null) {
mIconLoadState = LOAD_MULTI_ICONS;
itemsIconId = ValueParser.retrieveItemsIconId(ctlv);
menu.itemsIconSelfExplanatory = itemsIconId.selfExplanatory;
}
boolean presentTypeSpecified = (cmdDet.commandQualifier & 0x01) != 0;
if (presentTypeSpecified) {
if ((cmdDet.commandQualifier & 0x02) == 0) {
menu.presentationType = PresentationType.DATA_VALUES;
} else {
menu.presentationType = PresentationType.NAVIGATION_OPTIONS;
}
}
menu.softKeyPreferred = (cmdDet.commandQualifier & 0x04) != 0;
menu.helpAvailable = (cmdDet.commandQualifier & 0x80) != 0;
mCmdParams = new SelectItemParams(cmdDet, menu, titleIconId != null);
// Load icons data if needed.
switch(mIconLoadState) {
case LOAD_NO_ICON:
return false;
case LOAD_SINGLE_ICON:
mloadIcon = true;
mIconLoader.loadIcon(titleIconId.recordNumber, this
.obtainMessage(MSG_ID_LOAD_ICON_DONE));
break;
case LOAD_MULTI_ICONS:
int[] recordNumbers = itemsIconId.recordNumbers;
if (titleIconId != null) {
// Create a new array for all the icons (title and items).
recordNumbers = new int[itemsIconId.recordNumbers.length + 1];
recordNumbers[0] = titleIconId.recordNumber;
System.arraycopy(itemsIconId.recordNumbers, 0, recordNumbers,
1, itemsIconId.recordNumbers.length);
}
mloadIcon = true;
mIconLoader.loadIcons(recordNumbers, this
.obtainMessage(MSG_ID_LOAD_ICON_DONE));
break;
}
return true;
}
/**
* Processes EVENT_NOTIFY message from baseband.
*
* @param cmdDet Command Details container object.
* @param ctlvs List of ComprehensionTlv objects following Command Details
* object and Device Identities object within the proactive command
* @return true if the command is processing is pending and additional
* asynchronous processing is required.
*/
private boolean processEventNotify(CommandDetails cmdDet,
List<ComprehensionTlv> ctlvs) throws ResultException {
CatLog.d(this, "process EventNotify");
TextMessage textMsg = new TextMessage();
IconId iconId = null;
ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID,
ctlvs);
textMsg.text = ValueParser.retrieveAlphaId(ctlv);
ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
if (ctlv != null) {
iconId = ValueParser.retrieveIconId(ctlv);
textMsg.iconSelfExplanatory = iconId.selfExplanatory;
}
textMsg.responseNeeded = false;
mCmdParams = new DisplayTextParams(cmdDet, textMsg);
if (iconId != null) {
mloadIcon = true;
mIconLoadState = LOAD_SINGLE_ICON;
mIconLoader.loadIcon(iconId.recordNumber, this
.obtainMessage(MSG_ID_LOAD_ICON_DONE));
return true;
}
return false;
}
/**
* Processes SET_UP_EVENT_LIST proactive command from the SIM card.
*
* @param cmdDet Command Details object retrieved.
* @param ctlvs List of ComprehensionTlv objects following Command Details
* object and Device Identities object within the proactive command
* @return false. This function always returns false meaning that the command
* processing is not pending and additional asynchronous processing
* is not required.
*/
private boolean processSetUpEventList(CommandDetails cmdDet,
List<ComprehensionTlv> ctlvs) {
CatLog.d(this, "process SetUpEventList");
ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.EVENT_LIST, ctlvs);
if (ctlv != null) {
try {
byte[] rawValue = ctlv.getRawValue();
int valueIndex = ctlv.getValueIndex();
int valueLen = ctlv.getLength();
int[] eventList = new int[valueLen];
int eventValue = -1;
int i = 0;
while (valueLen > 0) {
eventValue = rawValue[valueIndex] & 0xff;
valueIndex++;
valueLen--;
switch (eventValue) {
case USER_ACTIVITY_EVENT:
case IDLE_SCREEN_AVAILABLE_EVENT:
case LANGUAGE_SELECTION_EVENT:
case BROWSER_TERMINATION_EVENT:
case BROWSING_STATUS_EVENT:
eventList[i] = eventValue;
i++;
break;
default:
break;
}
}
mCmdParams = new SetEventListParams(cmdDet, eventList);
} catch (IndexOutOfBoundsException e) {
CatLog.e(this, " IndexOutofBoundException in processSetUpEventList");
}
}
return false;
}
/**
* Processes LAUNCH_BROWSER proactive command from the SIM card.
*
* @param cmdDet Command Details container object.
* @param ctlvs List of ComprehensionTlv objects following Command Details
* object and Device Identities object within the proactive command
* @return true if the command is processing is pending and additional
* asynchronous processing is required.
* @throws ResultException
*/
private boolean processLaunchBrowser(CommandDetails cmdDet,
List<ComprehensionTlv> ctlvs) throws ResultException {
CatLog.d(this, "process LaunchBrowser");
TextMessage confirmMsg = new TextMessage();
IconId iconId = null;
String url = null;
ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.URL, ctlvs);
if (ctlv != null) {
try {
byte[] rawValue = ctlv.getRawValue();
int valueIndex = ctlv.getValueIndex();
int valueLen = ctlv.getLength();
if (valueLen > 0) {
url = GsmAlphabet.gsm8BitUnpackedToString(rawValue,
valueIndex, valueLen);
} else {
url = null;
}
} catch (IndexOutOfBoundsException e) {
throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
}
}
// parse alpha identifier.
ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID, ctlvs);
confirmMsg.text = ValueParser.retrieveAlphaId(ctlv);
// parse icon identifier
ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
if (ctlv != null) {
iconId = ValueParser.retrieveIconId(ctlv);
confirmMsg.iconSelfExplanatory = iconId.selfExplanatory;
}
// parse command qualifier value.
LaunchBrowserMode mode;
switch (cmdDet.commandQualifier) {
case 0x00:
default:
mode = LaunchBrowserMode.LAUNCH_IF_NOT_ALREADY_LAUNCHED;
break;
case 0x02:
mode = LaunchBrowserMode.USE_EXISTING_BROWSER;
break;
case 0x03:
mode = LaunchBrowserMode.LAUNCH_NEW_BROWSER;
break;
}
mCmdParams = new LaunchBrowserParams(cmdDet, confirmMsg, url, mode);
if (iconId != null) {
mIconLoadState = LOAD_SINGLE_ICON;
mIconLoader.loadIcon(iconId.recordNumber, this
.obtainMessage(MSG_ID_LOAD_ICON_DONE));
return true;
}
return false;
}
/**
* Processes PLAY_TONE proactive command from the SIM card.
*
* @param cmdDet Command Details container object.
* @param ctlvs List of ComprehensionTlv objects following Command Details
* object and Device Identities object within the proactive command
* @return true if the command is processing is pending and additional
* asynchronous processing is required.t
* @throws ResultException
*/
private boolean processPlayTone(CommandDetails cmdDet,
List<ComprehensionTlv> ctlvs) throws ResultException {
CatLog.d(this, "process PlayTone");
Tone tone = null;
TextMessage textMsg = new TextMessage();
Duration duration = null;
IconId iconId = null;
ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TONE, ctlvs);
if (ctlv != null) {
// Nothing to do for null objects.
if (ctlv.getLength() > 0) {
try {
byte[] rawValue = ctlv.getRawValue();
int valueIndex = ctlv.getValueIndex();
int toneVal = rawValue[valueIndex];
tone = Tone.fromInt(toneVal);
} catch (IndexOutOfBoundsException e) {
throw new ResultException(
ResultCode.CMD_DATA_NOT_UNDERSTOOD);
}
}
}
// parse alpha identifier
ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID, ctlvs);
if (ctlv != null) {
textMsg.text = ValueParser.retrieveAlphaId(ctlv);
}
// parse tone duration
ctlv = searchForTag(ComprehensionTlvTag.DURATION, ctlvs);
if (ctlv != null) {
duration = ValueParser.retrieveDuration(ctlv);
}
// parse icon identifier
ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
if (ctlv != null) {
iconId = ValueParser.retrieveIconId(ctlv);
textMsg.iconSelfExplanatory = iconId.selfExplanatory;
}
boolean vibrate = (cmdDet.commandQualifier & 0x01) != 0x00;
textMsg.responseNeeded = false;
mCmdParams = new PlayToneParams(cmdDet, textMsg, tone, duration, vibrate);
if (iconId != null) {
mIconLoadState = LOAD_SINGLE_ICON;
mIconLoader.loadIcon(iconId.recordNumber, this
.obtainMessage(MSG_ID_LOAD_ICON_DONE));
return true;
}
return false;
}
/**
* Processes SETUP_CALL proactive command from the SIM card.
*
* @param cmdDet Command Details object retrieved from the proactive command
* object
* @param ctlvs List of ComprehensionTlv objects following Command Details
* object and Device Identities object within the proactive command
* @return true if the command is processing is pending and additional
* asynchronous processing is required.
*/
private boolean processSetupCall(CommandDetails cmdDet,
List<ComprehensionTlv> ctlvs) throws ResultException {
CatLog.d(this, "process SetupCall");
Iterator<ComprehensionTlv> iter = ctlvs.iterator();
ComprehensionTlv ctlv = null;
// User confirmation phase message.
TextMessage confirmMsg = new TextMessage();
// Call set up phase message.
TextMessage callMsg = new TextMessage();
IconId confirmIconId = null;
IconId callIconId = null;
// get confirmation message string.
ctlv = searchForNextTag(ComprehensionTlvTag.ALPHA_ID, iter);
confirmMsg.text = ValueParser.retrieveAlphaId(ctlv);
ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
if (ctlv != null) {
confirmIconId = ValueParser.retrieveIconId(ctlv);
confirmMsg.iconSelfExplanatory = confirmIconId.selfExplanatory;
}
// get call set up message string.
ctlv = searchForNextTag(ComprehensionTlvTag.ALPHA_ID, iter);
if (ctlv != null) {
callMsg.text = ValueParser.retrieveAlphaId(ctlv);
}
ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
if (ctlv != null) {
callIconId = ValueParser.retrieveIconId(ctlv);
callMsg.iconSelfExplanatory = callIconId.selfExplanatory;
}
mCmdParams = new CallSetupParams(cmdDet, confirmMsg, callMsg);
if (confirmIconId != null || callIconId != null) {
mIconLoadState = LOAD_MULTI_ICONS;
int[] recordNumbers = new int[2];
recordNumbers[0] = confirmIconId != null
? confirmIconId.recordNumber : -1;
recordNumbers[1] = callIconId != null ? callIconId.recordNumber
: -1;
mIconLoader.loadIcons(recordNumbers, this
.obtainMessage(MSG_ID_LOAD_ICON_DONE));
return true;
}
return false;
}
private boolean processProvideLocalInfo(CommandDetails cmdDet, List<ComprehensionTlv> ctlvs)
throws ResultException {
CatLog.d(this, "process ProvideLocalInfo");
switch (cmdDet.commandQualifier) {
case DTTZ_SETTING:
CatLog.d(this, "PLI [DTTZ_SETTING]");
mCmdParams = new CommandParams(cmdDet);
break;
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;
}
private boolean processBIPClient(CommandDetails cmdDet,
List<ComprehensionTlv> ctlvs) throws ResultException {
AppInterface.CommandType commandType =
AppInterface.CommandType.fromInt(cmdDet.typeOfCommand);
if (commandType != null) {
CatLog.d(this, "process "+ commandType.name());
}
TextMessage textMsg = new TextMessage();
IconId iconId = null;
ComprehensionTlv ctlv = null;
boolean has_alpha_id = false;
// parse alpha identifier
ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID, ctlvs);
if (ctlv != null) {
textMsg.text = ValueParser.retrieveAlphaId(ctlv);
CatLog.d(this, "alpha TLV text=" + textMsg.text);
has_alpha_id = true;
}
// parse icon identifier
ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
if (ctlv != null) {
iconId = ValueParser.retrieveIconId(ctlv);
textMsg.iconSelfExplanatory = iconId.selfExplanatory;
}
textMsg.responseNeeded = false;
mCmdParams = new BIPClientParams(cmdDet, textMsg, has_alpha_id);
if (iconId != null) {
mIconLoadState = LOAD_SINGLE_ICON;
mIconLoader.loadIcon(iconId.recordNumber, obtainMessage(MSG_ID_LOAD_ICON_DONE));
return true;
}
return false;
}
public void dispose() {
mIconLoader.dispose();
mIconLoader = null;
mCmdParams = null;
mCaller = null;
sInstance = null;
}
}