STK App DSDS support
Change-Id: I8d0a9ac406327fa91d78119df2953a417b4e4cb6
diff --git a/src/com/android/stk/BootCompletedReceiver.java b/src/com/android/stk/BootCompletedReceiver.java
index 12cb32e..f11c4f3 100644
--- a/src/com/android/stk/BootCompletedReceiver.java
+++ b/src/com/android/stk/BootCompletedReceiver.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import com.android.internal.telephony.cat.CatLog;
/**
* Boot completed receiver. used to reset the app install state every time the
@@ -27,6 +28,8 @@
*
*/
public class BootCompletedReceiver extends BroadcastReceiver {
+ private static final String LOG_TAG = new Object(){}.getClass().getEnclosingClass().getName();
+
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
@@ -37,6 +40,7 @@
args.putInt(StkAppService.OPCODE, StkAppService.OP_BOOT_COMPLETED);
context.startService(new Intent(context, StkAppService.class)
.putExtras(args));
+ CatLog.d(LOG_TAG, "[ACTION_BOOT_COMPLETED]");
}
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/stk/StkAppInstaller.java b/src/com/android/stk/StkAppInstaller.java
index d9e96e9..3208ba8 100644
--- a/src/com/android/stk/StkAppInstaller.java
+++ b/src/com/android/stk/StkAppInstaller.java
@@ -17,45 +17,65 @@
package com.android.stk;
import com.android.internal.telephony.cat.CatLog;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.TelephonyProperties;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.telephony.TelephonyManager;
+import android.os.SystemProperties;
/**
* Application installer for SIM Toolkit.
*
*/
abstract class StkAppInstaller {
- private StkAppInstaller() {}
+ private static final String STK_LAUNCHER_ACTIVITY = "com.android.stk.StkLauncherActivity";
+ private static final String LOG_TAG = "StkAppInstaller";
- static void install(Context context) {
+ private StkAppInstaller() {
+ CatLog.d(LOG_TAG, "init");
+ }
+
+ public static void install(Context context) {
setAppState(context, true);
}
- static void unInstall(Context context) {
+ public static void unInstall(Context context) {
setAppState(context, false);
}
private static void setAppState(Context context, boolean install) {
+ CatLog.d(LOG_TAG, "[setAppState]+");
if (context == null) {
+ CatLog.d(LOG_TAG, "[setAppState]- no context, just return.");
return;
}
PackageManager pm = context.getPackageManager();
if (pm == null) {
+ CatLog.d(LOG_TAG, "[setAppState]- no package manager, just return.");
return;
}
- // check that STK app package is known to the PackageManager
- ComponentName cName = new ComponentName("com.android.stk",
- "com.android.stk.StkLauncherActivity");
+ ComponentName cName = new ComponentName("com.android.stk", STK_LAUNCHER_ACTIVITY);
int state = install ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
: PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
- try {
- pm.setComponentEnabledSetting(cName, state,
- PackageManager.DONT_KILL_APP);
- } catch (Exception e) {
- CatLog.d("StkAppInstaller", "Could not change STK app state");
+ if (((PackageManager.COMPONENT_ENABLED_STATE_ENABLED == state) &&
+ (PackageManager.COMPONENT_ENABLED_STATE_ENABLED ==
+ pm.getComponentEnabledSetting(cName))) ||
+ ((PackageManager.COMPONENT_ENABLED_STATE_DISABLED == state) &&
+ (PackageManager.COMPONENT_ENABLED_STATE_DISABLED ==
+ pm.getComponentEnabledSetting(cName)))) {
+ CatLog.d(LOG_TAG, "Need not change app state!!");
+ } else {
+ CatLog.d(LOG_TAG, "Change app state[" + install + "]");
+ try {
+ pm.setComponentEnabledSetting(cName, state, PackageManager.DONT_KILL_APP);
+ } catch (Exception e) {
+ CatLog.d(LOG_TAG, "Could not change STK app state");
+ }
}
+ CatLog.d(LOG_TAG, "[setAppState]-");
}
}
diff --git a/src/com/android/stk/StkAppService.java b/src/com/android/stk/StkAppService.java
old mode 100644
new mode 100755
index 24d5b89..1220741
--- a/src/com/android/stk/StkAppService.java
+++ b/src/com/android/stk/StkAppService.java
@@ -21,6 +21,10 @@
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.ActivityManager.RecentTaskInfo;
+import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -42,6 +46,10 @@
import android.widget.RemoteViews;
import android.widget.TextView;
import android.widget.Toast;
+import android.content.BroadcastReceiver;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
import com.android.internal.telephony.cat.AppInterface;
import com.android.internal.telephony.cat.Menu;
@@ -55,8 +63,14 @@
import com.android.internal.telephony.cat.TextMessage;
import com.android.internal.telephony.uicc.IccRefreshResponse;
import com.android.internal.telephony.uicc.IccCardStatus.CardState;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.uicc.UiccController;
import java.util.LinkedList;
+import java.lang.System;
+import java.util.List;
/**
* SIM toolkit application level service. Interacts with Telephopny messages,
@@ -66,23 +80,67 @@
public class StkAppService extends Service implements Runnable {
// members
+ protected class StkContext {
+ protected CatCmdMessage mMainCmd = null;
+ protected CatCmdMessage mCurrentCmd = null;
+ protected CatCmdMessage mCurrentMenuCmd = null;
+ protected Menu mCurrentMenu = null;
+ protected String lastSelectedItem = null;
+ protected boolean mMenuIsVisible = false;
+ protected boolean mIsInputPending = false;
+ protected boolean mIsMenuPending = false;
+ protected boolean mIsDialogPending = false;
+ protected boolean responseNeeded = true;
+ protected boolean launchBrowser = false;
+ protected BrowserSettings mBrowserSettings = null;
+ protected LinkedList<DelayedCmd> mCmdsQ = null;
+ protected boolean mCmdInProgress = false;
+ protected int mStkServiceState = STATE_UNKNOWN;
+ protected int mSetupMenuState = STATE_UNKNOWN;
+ protected int mMenuState = StkMenuActivity.STATE_INIT;
+ protected int mOpCode = -1;
+ private Activity mActivityInstance = null;
+ private Activity mDialogInstance = null;
+ private Activity mMainActivityInstance = null;
+ private boolean mBackGroundTRSent = false;
+ private int mSlotId = 0;
+ final synchronized void setPendingActivityInstance(Activity act) {
+ CatLog.d(this, "setPendingActivityInstance act : " + mSlotId + ", " + act);
+ callSetActivityInstMsg(OP_SET_ACT_INST, mSlotId, act);
+ }
+ final synchronized Activity getPendingActivityInstance() {
+ CatLog.d(this, "getPendingActivityInstance act : " + mSlotId + ", " +
+ mActivityInstance);
+ return mActivityInstance;
+ }
+ final synchronized void setPendingDialogInstance(Activity act) {
+ CatLog.d(this, "setPendingDialogInstance act : " + mSlotId + ", " + act);
+ callSetActivityInstMsg(OP_SET_DAL_INST, mSlotId, act);
+ }
+ final synchronized Activity getPendingDialogInstance() {
+ CatLog.d(this, "getPendingDialogInstance act : " + mSlotId + ", " +
+ mDialogInstance);
+ return mDialogInstance;
+ }
+ final synchronized void setMainActivityInstance(Activity act) {
+ CatLog.d(this, "setMainActivityInstance act : " + mSlotId + ", " + act);
+ callSetActivityInstMsg(OP_SET_MAINACT_INST, mSlotId, act);
+ }
+ final synchronized Activity getMainActivityInstance() {
+ CatLog.d(this, "getMainActivityInstance act : " + mSlotId + ", " +
+ mMainActivityInstance);
+ return mMainActivityInstance;
+ }
+ }
+
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
- private AppInterface mStkService;
private Context mContext = null;
- private CatCmdMessage mMainCmd = null;
- private CatCmdMessage mCurrentCmd = null;
- private Menu mCurrentMenu = null;
- private String lastSelectedItem = null;
- private boolean mMenuIsVisibile = false;
- private boolean responseNeeded = true;
- private boolean mCmdInProgress = false;
private NotificationManager mNotificationManager = null;
- private LinkedList<DelayedCmd> mCmdsQ = null;
- private boolean launchBrowser = false;
- private BrowserSettings mBrowserSettings = null;
static StkAppService sInstance = null;
-
+ private AppInterface[] mStkService = null;
+ private StkContext[] mStkContext = null;
+ private int mSimCount = 0;
// Used for setting FLAG_ACTIVITY_NO_USER_ACTION when
// creating an intent.
private enum InitiatedByUserAction {
@@ -99,7 +157,12 @@
static final String HELP = "help";
static final String CONFIRMATION = "confirm";
static final String CHOICE = "choice";
-
+ static final String SLOT_ID = "SLOT_ID";
+ static final String STK_CMD = "STK CMD";
+ static final String STK_DIALOG_URI = "stk://com.android.stk/dialog/";
+ static final String STK_MENU_URI = "stk://com.android.stk/menu/";
+ static final String STK_INPUT_URI = "stk://com.android.stk/input/";
+ static final String STK_TONE_URI = "stk://com.android.stk/tone/";
// operations ids for different service functionality.
static final int OP_CMD = 1;
static final int OP_RESPONSE = 2;
@@ -108,6 +171,9 @@
static final int OP_BOOT_COMPLETED = 5;
private static final int OP_DELAYED_MSG = 6;
static final int OP_CARD_STATUS_CHANGED = 7;
+ static final int OP_SET_ACT_INST = 8;
+ static final int OP_SET_DAL_INST = 9;
+ static final int OP_SET_MAINACT_INST = 10;
// Response ids
static final int RES_ID_MENU_SELECTION = 11;
@@ -124,14 +190,17 @@
static final int YES = 1;
static final int NO = 0;
- private static final String PACKAGE_NAME = "com.android.stk";
- private static final String MENU_ACTIVITY_NAME =
- PACKAGE_NAME + ".StkMenuActivity";
- private static final String INPUT_ACTIVITY_NAME =
- PACKAGE_NAME + ".StkInputActivity";
+ static final int STATE_UNKNOWN = -1;
+ static final int STATE_NOT_EXIST = 0;
+ static final int STATE_EXIST = 1;
+ private static final String PACKAGE_NAME = "com.android.stk";
+ private static final String STK_MENU_ACTIVITY_NAME = PACKAGE_NAME + ".StkMenuActivity";
+ private static final String STK_INPUT_ACTIVITY_NAME = PACKAGE_NAME + ".StkInputActivity";
+ private static final String STK_DIALOG_ACTIVITY_NAME = PACKAGE_NAME + ".StkDialogActivity";
// Notification id used to display Idle Mode text in NotificationManager.
private static final int STK_NOTIFICATION_ID = 333;
+ private static final String LOG_TAG = new Object(){}.getClass().getEnclosingClass().getName();
// Inner class used for queuing telephony messages (proactive commands,
// session end) while the service is busy processing a previous message.
@@ -139,20 +208,41 @@
// members
int id;
CatCmdMessage msg;
+ int slotId;
- DelayedCmd(int id, CatCmdMessage msg) {
+ DelayedCmd(int id, CatCmdMessage msg, int slotId) {
this.id = id;
this.msg = msg;
+ this.slotId = slotId;
}
}
@Override
public void onCreate() {
+ CatLog.d(LOG_TAG, "onCreate()+");
// Initialize members
- mCmdsQ = new LinkedList<DelayedCmd>();
+ int i = 0;
+ mContext = getBaseContext();
+ mSimCount = TelephonyManager.from(mContext).getSimCount();
+ CatLog.d(LOG_TAG, "simCount: " + mSimCount);
+ mStkService = new AppInterface[mSimCount];
+ mStkContext = new StkContext[mSimCount];
+ for (i = 0; i < mSimCount; i++) {
+ CatLog.d(LOG_TAG, "slotId: " + i);
+ if (null != UiccController.getInstance() && null != UiccController.getInstance()
+ .getUiccCard(i)) {
+ mStkService[i] = UiccController.getInstance().getUiccCard(i).getCatService();
+ } else {
+ CatLog.d(LOG_TAG, "Null instance: [" + UiccController.getInstance() + "],[" +
+ UiccController.getInstance().getUiccCard(i) + "]");
+ }
+ mStkContext[i] = new StkContext();
+ mStkContext[i].mSlotId = i;
+ mStkContext[i].mCmdsQ = new LinkedList<DelayedCmd>();
+ }
+
Thread serviceThread = new Thread(null, this, "Stk App Service");
serviceThread.start();
- mContext = getBaseContext();
mNotificationManager = (NotificationManager) mContext
.getSystemService(Context.NOTIFICATION_SERVICE);
sInstance = this;
@@ -160,17 +250,55 @@
@Override
public void onStart(Intent intent, int startId) {
-
- mStkService = com.android.internal.telephony.cat.CatService
- .getInstance();
-
- if (mStkService == null) {
- stopSelf();
- CatLog.d(this, " Unable to get Service handle");
- StkAppInstaller.unInstall(mContext);
+ if (intent == null) {
+ CatLog.d(LOG_TAG, "StkAppService onStart intent is null so return");
return;
}
+ Bundle args = intent.getExtras();
+ if (args == null) {
+ CatLog.d(LOG_TAG, "StkAppService onStart args is null so return");
+ return;
+ }
+
+ int op = args.getInt(OPCODE);
+ int slotId = 0;
+ int i = 0;
+ if (op != OP_BOOT_COMPLETED) {
+ slotId = args.getInt(SLOT_ID);
+ }
+ CatLog.d(LOG_TAG, "onStart sim id: " + slotId + ", op: " + op + ", " + args);
+ if ((slotId >= 0 && slotId < mSimCount) && mStkService[slotId] == null) {
+ if (null != UiccController.getInstance() && null != UiccController.getInstance()
+ .getUiccCard(slotId)) {
+ mStkService[slotId] = UiccController.getInstance().getUiccCard(slotId)
+ .getCatService();
+ } else {
+ CatLog.d(LOG_TAG, "Null instance: [" + UiccController.getInstance() + "],[" +
+ UiccController.getInstance().getUiccCard(slotId)+"]");
+ }
+ if (mStkService[slotId] == null) {
+ CatLog.d(LOG_TAG, "mStkService is: " + mStkContext[slotId].mStkServiceState);
+ mStkContext[slotId].mStkServiceState = STATE_NOT_EXIST;
+ //Check other StkService state.
+ //If all StkServices are not available, stop itself and uninstall apk.
+ for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
+ if (i != slotId
+ && (mStkContext[i].mStkServiceState == STATE_UNKNOWN
+ || mStkContext[i].mStkServiceState == STATE_EXIST)) {
+ break;
+ }
+ }
+ } else {
+ mStkContext[slotId].mStkServiceState = STATE_EXIST;
+ }
+ if (i == mSimCount) {
+ stopSelf();
+ StkAppInstaller.unInstall(mContext);
+ return;
+ }
+ }
+
waitForLooper();
// onStart() method can be passed a null intent
// TODO: replace onStart() with onStartCommand()
@@ -178,14 +306,9 @@
return;
}
- Bundle args = intent.getExtras();
-
- if (args == null) {
- return;
- }
-
Message msg = mServiceHandler.obtainMessage();
- msg.arg1 = args.getInt(OPCODE);
+ msg.arg1 = op;
+ msg.arg2 = slotId;
switch(msg.arg1) {
case OP_CMD:
msg.obj = args.getParcelable(CMD_MSG);
@@ -206,6 +329,7 @@
@Override
public void onDestroy() {
+ CatLog.d(LOG_TAG, "onDestroy()");
waitForLooper();
mServiceLooper.quit();
}
@@ -227,15 +351,58 @@
/*
* Package api used by StkMenuActivity to indicate if its on the foreground.
*/
- void indicateMenuVisibility(boolean visibility) {
- mMenuIsVisibile = visibility;
+ void indicateMenuVisibility(boolean visibility, int slotId) {
+ if (slotId >= 0 && slotId < mSimCount) {
+ mStkContext[slotId].mMenuIsVisible = visibility;
+ }
+ }
+
+ boolean isInputPending(int slotId) {
+ if (slotId >= 0 && slotId < mSimCount) {
+ CatLog.d(LOG_TAG, "isInputFinishBySrv: " + mStkContext[slotId].mIsInputPending);
+ return mStkContext[slotId].mIsInputPending;
+ }
+ return false;
+ }
+
+ boolean isMenuPending(int slotId) {
+ if (slotId >= 0 && slotId < mSimCount) {
+ CatLog.d(LOG_TAG, "isMenuPending: " + mStkContext[slotId].mIsMenuPending);
+ return mStkContext[slotId].mIsMenuPending;
+ }
+ return false;
+ }
+
+ boolean isDialogPending(int slotId) {
+ if (slotId >= 0 && slotId < mSimCount) {
+ CatLog.d(LOG_TAG, "isDialogPending: " + mStkContext[slotId].mIsDialogPending);
+ return mStkContext[slotId].mIsDialogPending;
+ }
+ return false;
}
/*
* Package api used by StkMenuActivity to get its Menu parameter.
*/
- Menu getMenu() {
- return mCurrentMenu;
+ Menu getMenu(int slotId) {
+ CatLog.d(LOG_TAG, "StkAppService, getMenu, sim id: " + slotId);
+ if (slotId >=0 && slotId < mSimCount) {
+ return mStkContext[slotId].mCurrentMenu;
+ } else {
+ return null;
+ }
+ }
+
+ /*
+ * Package api used by StkMenuActivity to get its Main Menu parameter.
+ */
+ Menu getMainMenu(int slotId) {
+ CatLog.d(LOG_TAG, "StkAppService, getMainMenu, sim id: " + slotId);
+ if (slotId >=0 && slotId < mSimCount) {
+ return mStkContext[slotId].mMainCmd.getMenu();
+ } else {
+ return null;
+ }
}
/*
@@ -260,17 +427,69 @@
private final class ServiceHandler extends Handler {
@Override
public void handleMessage(Message msg) {
+ if(null == msg) {
+ CatLog.d(LOG_TAG, "ServiceHandler handleMessage msg is null");
+ return;
+ }
int opcode = msg.arg1;
+ int slotId = msg.arg2;
+ CatLog.d(LOG_TAG, "handleMessage opcode[" + opcode + "], sim id[" + slotId + "]");
+ if (opcode == OP_CMD && msg.obj != null &&
+ ((CatCmdMessage)msg.obj).getCmdType()!= null) {
+ CatLog.d(LOG_TAG, "cmdName[" + ((CatCmdMessage)msg.obj).getCmdType().name() + "]");
+ }
+ mStkContext[slotId].mOpCode = opcode;
switch (opcode) {
case OP_LAUNCH_APP:
- if (mMainCmd == null) {
+ if (mStkContext[slotId].mMainCmd == null) {
+ CatLog.d(LOG_TAG, "mMainCmd is null");
// nothing todo when no SET UP MENU command didn't arrive.
return;
}
- launchMenuActivity(null);
+ CatLog.d(LOG_TAG, "handleMessage OP_LAUNCH_APP - mCmdInProgress[" +
+ mStkContext[slotId].mCmdInProgress + "]");
+
+ //If there is a pending activity for the slot id,
+ //just finish it and create a new one to handle the pending command.
+ cleanUpInstanceStackBySlot(slotId);
+
+ //Clean up all other activities in stack.
+ for (int i = 0; i < mSimCount; i++) {
+ if (i != slotId && mStkContext[i].mCurrentCmd != null) {
+ Activity otherAct = mStkContext[i].getPendingActivityInstance();
+ Activity otherDal = mStkContext[i].getPendingDialogInstance();
+ Activity otherMainMenu = mStkContext[i].getMainActivityInstance();
+ if (otherAct != null) {
+ CatLog.d(LOG_TAG, "finish pending otherAct and send SE. slot: " + i);
+ // Send end session for the pending proactive command of slot i in
+ // onDestroy of the activity.
+ // Set mBackGroundTRSent to true for ignoring to show the main menu
+ // for the following end session event.
+ mStkContext[i].mBackGroundTRSent = true;
+ otherAct.finish();
+ mStkContext[i].mActivityInstance = null;
+ }
+ if (otherDal != null) {
+ CatLog.d(LOG_TAG, "finish pending otherDal and send TR for the dialog");
+ mStkContext[i].mBackGroundTRSent = true;
+ otherDal.finish();
+ mStkContext[i].mDialogInstance = null;
+ }
+ if (otherMainMenu != null) {
+ CatLog.d(LOG_TAG, "finish pending otherMainMenu.");
+ otherMainMenu.finish();
+ mStkContext[i].mMainActivityInstance = null;
+ }
+ }
+ }
+ CatLog.d(LOG_TAG, "Current cmd type: " +
+ mStkContext[slotId].mCurrentCmd.getCmdType());
+ //Restore the last command from stack by slot id.
+ restoreInstanceFromStackBySlot(slotId);
break;
case OP_CMD:
+ CatLog.d(LOG_TAG, "[OP_CMD]");
CatCmdMessage cmdMsg = (CatCmdMessage) msg.obj;
// There are two types of commands:
// 1. Interactive - user's response is required.
@@ -281,85 +500,134 @@
// is already in progress, we need to queue the next command until
// the user has responded or a timeout expired.
if (!isCmdInteractive(cmdMsg)) {
- handleCmd(cmdMsg);
+ handleCmd(cmdMsg, slotId);
} else {
- if (!mCmdInProgress) {
- mCmdInProgress = true;
- handleCmd((CatCmdMessage) msg.obj);
+ if (!mStkContext[slotId].mCmdInProgress) {
+ mStkContext[slotId].mCmdInProgress = true;
+ handleCmd((CatCmdMessage) msg.obj, slotId);
} else {
- mCmdsQ.addLast(new DelayedCmd(OP_CMD,
- (CatCmdMessage) msg.obj));
+ CatLog.d(LOG_TAG, "[Interactive][in progress]");
+ mStkContext[slotId].mCmdsQ.addLast(new DelayedCmd(OP_CMD,
+ (CatCmdMessage) msg.obj, slotId));
}
}
break;
case OP_RESPONSE:
- if (responseNeeded) {
- handleCmdResponse((Bundle) msg.obj);
+ if (mStkContext[slotId].responseNeeded) {
+ handleCmdResponse((Bundle) msg.obj, slotId);
}
// call delayed commands if needed.
- if (mCmdsQ.size() != 0) {
- callDelayedMsg();
+ if (mStkContext[slotId].mCmdsQ.size() != 0) {
+ callDelayedMsg(slotId);
} else {
- mCmdInProgress = false;
+ mStkContext[slotId].mCmdInProgress = false;
}
// reset response needed state var to its original value.
- responseNeeded = true;
+ mStkContext[slotId].responseNeeded = true;
break;
case OP_END_SESSION:
- if (!mCmdInProgress) {
- mCmdInProgress = true;
- handleSessionEnd();
+ if (!mStkContext[slotId].mCmdInProgress) {
+ mStkContext[slotId].mCmdInProgress = true;
+ handleSessionEnd(slotId);
} else {
- mCmdsQ.addLast(new DelayedCmd(OP_END_SESSION, null));
+ mStkContext[slotId].mCmdsQ.addLast(
+ new DelayedCmd(OP_END_SESSION, null, slotId));
}
break;
case OP_BOOT_COMPLETED:
- CatLog.d(this, "OP_BOOT_COMPLETED");
- if (mMainCmd == null) {
+ CatLog.d(LOG_TAG, " OP_BOOT_COMPLETED");
+ int i = 0;
+ for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
+ if (mStkContext[i].mMainCmd != null) {
+ break;
+ }
+ }
+ if (i == mSimCount) {
StkAppInstaller.unInstall(mContext);
}
break;
case OP_DELAYED_MSG:
- handleDelayedCmd();
+ handleDelayedCmd(slotId);
break;
case OP_CARD_STATUS_CHANGED:
- CatLog.d(this, "Card/Icc Status change received");
- handleCardStatusChangeAndIccRefresh((Bundle) msg.obj);
+ CatLog.d(LOG_TAG, "Card/Icc Status change received");
+ handleCardStatusChangeAndIccRefresh((Bundle) msg.obj, slotId);
+ break;
+ case OP_SET_ACT_INST:
+ Activity act = new Activity();
+ act = (Activity) msg.obj;
+ CatLog.d(LOG_TAG, "Set activity instance. " + act);
+ mStkContext[slotId].mActivityInstance = act;
+ break;
+ case OP_SET_DAL_INST:
+ Activity dal = new Activity();
+ CatLog.d(LOG_TAG, "Set dialog instance. " + dal);
+ dal = (Activity) msg.obj;
+ mStkContext[slotId].mDialogInstance = dal;
+ break;
+ case OP_SET_MAINACT_INST:
+ Activity mainAct = new Activity();
+ mainAct = (Activity) msg.obj;
+ CatLog.d(LOG_TAG, "Set activity instance. " + mainAct);
+ mStkContext[slotId].mMainActivityInstance = mainAct;
break;
}
}
- private void handleCardStatusChangeAndIccRefresh(Bundle args) {
+ private void handleCardStatusChangeAndIccRefresh(Bundle args, int slotId) {
boolean cardStatus = args.getBoolean(AppInterface.CARD_STATUS);
- CatLog.d(this, "CardStatus: " + cardStatus);
+ CatLog.d(LOG_TAG, "CardStatus: " + cardStatus);
if (cardStatus == false) {
- CatLog.d(this, "CARD is ABSENT");
+ CatLog.d(LOG_TAG, "CARD is ABSENT");
// Uninstall STKAPP, Clear Idle text, Stop StkAppService
- StkAppInstaller.unInstall(mContext);
- mNotificationManager.cancel(STK_NOTIFICATION_ID);
- stopSelf();
+ mNotificationManager.cancel(getNotificationId(slotId));
+ if (isAllOtherCardsAbsent(slotId)) {
+ CatLog.d(LOG_TAG, "All CARDs are ABSENT");
+ StkAppInstaller.unInstall(mContext);
+ stopSelf();
+ }
} else {
IccRefreshResponse state = new IccRefreshResponse();
state.refreshResult = args.getInt(AppInterface.REFRESH_RESULT);
- CatLog.d(this, "Icc Refresh Result: "+ state.refreshResult);
+ CatLog.d(LOG_TAG, "Icc Refresh Result: "+ state.refreshResult);
if ((state.refreshResult == IccRefreshResponse.REFRESH_RESULT_INIT) ||
(state.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET)) {
// Clear Idle Text
- mNotificationManager.cancel(STK_NOTIFICATION_ID);
+ mNotificationManager.cancel(getNotificationId(slotId));
}
if (state.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET) {
// Uninstall STkmenu
- StkAppInstaller.unInstall(mContext);
- mCurrentMenu = null;
- mMainCmd = null;
+ if (isAllOtherCardsAbsent(slotId)) {
+ StkAppInstaller.unInstall(mContext);
+ }
+ mStkContext[slotId].mCurrentMenu = null;
+ mStkContext[slotId].mMainCmd = null;
}
}
}
}
+ /*
+ * Check if all SIMs are absent except the id of slot equals "slotId".
+ */
+ private boolean isAllOtherCardsAbsent(int slotId) {
+ TelephonyManager mTm = (TelephonyManager) mContext.getSystemService(
+ Context.TELEPHONY_SERVICE);
+ int i = 0;
+ for (i = 0; i < mSimCount; i++) {
+ if (i != slotId && mTm.hasIccCard(i)) {
+ break;
+ }
+ }
+ if (i == mSimCount) {
+ return true;
+ } else {
+ return false;
+ }
+ }
private boolean isCmdInteractive(CatCmdMessage cmd) {
switch (cmd.getCmdType()) {
case SEND_DTMF:
@@ -377,123 +645,182 @@
return true;
}
- private void handleDelayedCmd() {
- if (mCmdsQ.size() != 0) {
- DelayedCmd cmd = mCmdsQ.poll();
- switch (cmd.id) {
- case OP_CMD:
- handleCmd(cmd.msg);
- break;
- case OP_END_SESSION:
- handleSessionEnd();
- break;
+ private void handleDelayedCmd(int slotId) {
+ CatLog.d(LOG_TAG, "handleDelayedCmd, slotId: " + slotId);
+ if (mStkContext[slotId].mCmdsQ.size() != 0) {
+ DelayedCmd cmd = mStkContext[slotId].mCmdsQ.poll();
+ if (cmd != null) {
+ CatLog.d(LOG_TAG, "handleDelayedCmd - queue size: " +
+ mStkContext[slotId].mCmdsQ.size() +
+ " id: " + cmd.id + "sim id: " + cmd.slotId);
+ switch (cmd.id) {
+ case OP_CMD:
+ handleCmd(cmd.msg, cmd.slotId);
+ break;
+ case OP_END_SESSION:
+ handleSessionEnd(cmd.slotId);
+ break;
+ }
}
}
}
- private void callDelayedMsg() {
+ private void callDelayedMsg(int slotId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = OP_DELAYED_MSG;
+ msg.arg2 = slotId;
mServiceHandler.sendMessage(msg);
}
- private void handleSessionEnd() {
- mCurrentCmd = mMainCmd;
- lastSelectedItem = null;
+ private void callSetActivityInstMsg(int inst_type, int slotId, Object obj) {
+ Message msg = mServiceHandler.obtainMessage();
+ msg.obj = obj;
+ msg.arg1 = inst_type;
+ msg.arg2 = slotId;
+ mServiceHandler.sendMessage(msg);
+ }
+
+ private void handleSessionEnd(int slotId) {
+ mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
+ CatLog.d(LOG_TAG, "[handleSessionEnd] - mCurrentCmd changed to mMainCmd!.");
+ mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mMainCmd;
+ CatLog.d(LOG_TAG, "slotId: " + slotId + ", mMenuState: " +
+ mStkContext[slotId].mMenuState);
+
+ mStkContext[slotId].mIsInputPending = false;
+ mStkContext[slotId].mIsMenuPending = false;
+ mStkContext[slotId].mIsDialogPending = false;
+
+ // We should finish all pending activity if receiving END SESSION command.
+ cleanUpInstanceStackBySlot(slotId);
+
+ if (mStkContext[slotId].mMainCmd == null) {
+ CatLog.d(LOG_TAG, "[handleSessionEnd][mMainCmd is null!]");
+ }
+ mStkContext[slotId].lastSelectedItem = null;
// In case of SET UP MENU command which removed the app, don't
// update the current menu member.
- if (mCurrentMenu != null && mMainCmd != null) {
- mCurrentMenu = mMainCmd.getMenu();
+ if (mStkContext[slotId].mCurrentMenu != null && mStkContext[slotId].mMainCmd != null) {
+ mStkContext[slotId].mCurrentMenu = mStkContext[slotId].mMainCmd.getMenu();
}
- if (mMenuIsVisibile) {
- launchMenuActivity(null);
+ CatLog.d(LOG_TAG, "[handleSessionEnd][mMenuState]" + mStkContext[slotId].mMenuIsVisible);
+ // In mutiple instance architecture, the main menu for slotId will be finished when user
+ // goes to the Stk menu of the other SIM. So, we should launch a new instance for the
+ // main menu if the main menu instance has been finished.
+ // If the current menu is secondary menu, we should launch main menu.
+ if (StkMenuActivity.STATE_SECONDARY == mStkContext[slotId].mMenuState) {
+ launchMenuActivity(null, slotId);
}
- if (mCmdsQ.size() != 0) {
- callDelayedMsg();
+ if (mStkContext[slotId].mCmdsQ.size() != 0) {
+ callDelayedMsg(slotId);
} else {
- mCmdInProgress = false;
+ mStkContext[slotId].mCmdInProgress = false;
}
// In case a launch browser command was just confirmed, launch that url.
- if (launchBrowser) {
- launchBrowser = false;
- launchBrowser(mBrowserSettings);
+ if (mStkContext[slotId].launchBrowser) {
+ mStkContext[slotId].launchBrowser = false;
+ launchBrowser(mStkContext[slotId].mBrowserSettings);
}
}
- private void handleCmd(CatCmdMessage cmdMsg) {
+ private void handleCmd(CatCmdMessage cmdMsg, int slotId) {
if (cmdMsg == null) {
return;
}
// save local reference for state tracking.
- mCurrentCmd = cmdMsg;
+ mStkContext[slotId].mCurrentCmd = cmdMsg;
boolean waitForUsersResponse = true;
- CatLog.d(this, cmdMsg.getCmdType().name());
+ mStkContext[slotId].mIsInputPending = false;
+ mStkContext[slotId].mIsMenuPending = false;
+ mStkContext[slotId].mIsDialogPending = false;
+
+ CatLog.d(LOG_TAG,"[handleCmd]" + cmdMsg.getCmdType().name());
switch (cmdMsg.getCmdType()) {
case DISPLAY_TEXT:
TextMessage msg = cmdMsg.geTextMessage();
- responseNeeded = msg.responseNeeded;
+ mStkContext[slotId].responseNeeded = msg.responseNeeded;
waitForUsersResponse = msg.responseNeeded;
- if (lastSelectedItem != null) {
- msg.title = lastSelectedItem;
- } else if (mMainCmd != null){
- msg.title = mMainCmd.getMenu().title;
+ if (mStkContext[slotId].lastSelectedItem != null) {
+ msg.title = mStkContext[slotId].lastSelectedItem;
+ } else if (mStkContext[slotId].mMainCmd != null){
+ msg.title = mStkContext[slotId].mMainCmd.getMenu().title;
} else {
// TODO: get the carrier name from the SIM
msg.title = "";
}
- launchTextDialog();
+ launchTextDialog(slotId);
break;
case SELECT_ITEM:
- mCurrentMenu = cmdMsg.getMenu();
- launchMenuActivity(cmdMsg.getMenu());
+ CatLog.d(LOG_TAG, "SELECT_ITEM +");
+ mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
+ mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
+ launchMenuActivity(cmdMsg.getMenu(), slotId);
break;
case SET_UP_MENU:
- mMainCmd = mCurrentCmd;
- mCurrentMenu = cmdMsg.getMenu();
- if (removeMenu()) {
- CatLog.d(this, "Uninstall App");
- mCurrentMenu = null;
- StkAppInstaller.unInstall(mContext);
+ mStkContext[slotId].mCmdInProgress = false;
+ mStkContext[slotId].mMainCmd = mStkContext[slotId].mCurrentCmd;
+ mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
+ mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
+ CatLog.d(LOG_TAG, "SET_UP_MENU [" + removeMenu(slotId) + "]");
+
+ if (removeMenu(slotId)) {
+ int i = 0;
+ CatLog.d(LOG_TAG, "removeMenu() - Uninstall App");
+ mStkContext[slotId].mCurrentMenu = null;
+ //Check other setup menu state. If all setup menu are removed, uninstall apk.
+ for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
+ if (i != slotId
+ && (mStkContext[slotId].mSetupMenuState == STATE_UNKNOWN
+ || mStkContext[slotId].mSetupMenuState == STATE_EXIST)) {
+ CatLog.d(LOG_TAG, "Not Uninstall App:" + i + ","
+ + mStkContext[slotId].mSetupMenuState);
+ break;
+ }
+ }
+ if (i == mSimCount) {
+ StkAppInstaller.unInstall(mContext);
+ }
} else {
- CatLog.d(this, "Install App");
+ CatLog.d(LOG_TAG, "install App");
StkAppInstaller.install(mContext);
}
- if (mMenuIsVisibile) {
- launchMenuActivity(null);
+ if (mStkContext[slotId].mMenuIsVisible) {
+ launchMenuActivity(null, slotId);
}
break;
case GET_INPUT:
case GET_INKEY:
- launchInputActivity();
+ launchInputActivity(slotId);
break;
case SET_UP_IDLE_MODE_TEXT:
waitForUsersResponse = false;
- launchIdleText();
+ launchIdleText(slotId);
break;
case SEND_DTMF:
case SEND_SMS:
case SEND_SS:
case SEND_USSD:
waitForUsersResponse = false;
- launchEventMessage();
+ launchEventMessage(slotId);
break;
case LAUNCH_BROWSER:
- launchConfirmationDialog(mCurrentCmd.geTextMessage());
+ launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.geTextMessage(), slotId);
break;
case SET_UP_CALL:
- launchConfirmationDialog(mCurrentCmd.getCallSettings().confirmMsg);
+ launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.getCallSettings()
+ .confirmMsg, slotId);
break;
case PLAY_TONE:
- launchToneDialog();
+ launchToneDialog(slotId);
break;
case OPEN_CHANNEL:
- launchOpenChannelDialog();
+ launchOpenChannelDialog(slotId);
break;
case CLOSE_CHANNEL:
case RECEIVE_DATA:
case SEND_DATA:
- TextMessage m = mCurrentCmd.geTextMessage();
+ TextMessage m = mStkContext[slotId].mCurrentCmd.geTextMessage();
if ((m != null) && (m.text == null)) {
switch(cmdMsg.getCmdType()) {
@@ -511,33 +838,43 @@
/*
* Display indication in the form of a toast to the user if required.
*/
- launchEventMessage();
+ launchEventMessage(slotId);
break;
}
if (!waitForUsersResponse) {
- if (mCmdsQ.size() != 0) {
- callDelayedMsg();
+ if (mStkContext[slotId].mCmdsQ.size() != 0) {
+ callDelayedMsg(slotId);
} else {
- mCmdInProgress = false;
+ mStkContext[slotId].mCmdInProgress = false;
}
}
}
- private void handleCmdResponse(Bundle args) {
- if (mCurrentCmd == null) {
+ private void handleCmdResponse(Bundle args, int slotId) {
+ CatLog.d(LOG_TAG, "handleCmdResponse, sim id: " + slotId);
+ if (mStkContext[slotId].mCurrentCmd == null) {
return;
}
- if (mStkService == null) {
- mStkService = com.android.internal.telephony.cat.CatService.getInstance();
- if (mStkService == null) {
+
+ if (mStkService[slotId] == null) {
+ if(null != UiccController.getInstance() &&
+ null != UiccController.getInstance().getUiccCard(slotId)) {
+ mStkService[slotId] = UiccController.getInstance().getUiccCard(slotId)
+ .getCatService();
+ } else {
+ CatLog.d(LOG_TAG, "Null instance: [" + UiccController.getInstance() +
+ "],["+UiccController.getInstance().getUiccCard(slotId)+"]");
+ }
+ if (mStkService[slotId] == null) {
// This should never happen (we should be responding only to a message
// that arrived from StkService). It has to exist by this time
+ CatLog.d(LOG_TAG, "Exception! mStkService is null when we need to send response.");
throw new RuntimeException("mStkService is null when we need to send response");
}
}
- CatResponseMessage resMsg = new CatResponseMessage(mCurrentCmd);
+ CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentCmd);
// set result code
boolean helpRequired = args.getBoolean(HELP, false);
@@ -545,12 +882,13 @@
switch(args.getInt(RES_ID)) {
case RES_ID_MENU_SELECTION:
- CatLog.d(this, "RES_ID_MENU_SELECTION");
+ CatLog.d(LOG_TAG, "MENU_SELECTION=" + mStkContext[slotId].
+ mCurrentMenuCmd.getCmdType());
int menuSelection = args.getInt(MENU_SELECTION);
- switch(mCurrentCmd.getCmdType()) {
+ switch(mStkContext[slotId].mCurrentMenuCmd.getCmdType()) {
case SET_UP_MENU:
case SELECT_ITEM:
- lastSelectedItem = getItemName(menuSelection);
+ mStkContext[slotId].lastSelectedItem = getItemName(menuSelection, slotId);
if (helpRequired) {
resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
} else {
@@ -561,10 +899,10 @@
}
break;
case RES_ID_INPUT:
- CatLog.d(this, "RES_ID_INPUT");
+ CatLog.d(LOG_TAG, "RES_ID_INPUT");
String input = args.getString(INPUT);
- Input cmdInput = mCurrentCmd.geInput();
- if (cmdInput != null && cmdInput.yesNo) {
+ if (input != null && (null != mStkContext[slotId].mCurrentCmd.geInput()) &&
+ (mStkContext[slotId].mCurrentCmd.geInput().yesNo)) {
boolean yesNoSelection = input
.equals(StkInputActivity.YES_STR_RESPONSE);
resMsg.setYesNo(yesNoSelection);
@@ -580,7 +918,7 @@
case RES_ID_CONFIRM:
CatLog.d(this, "RES_ID_CONFIRM");
confirmed = args.getBoolean(CONFIRMATION);
- switch (mCurrentCmd.getCmdType()) {
+ switch (mStkContext[slotId].mCurrentCmd.getCmdType()) {
case DISPLAY_TEXT:
resMsg.setResultCode(confirmed ? ResultCode.OK
: ResultCode.UICC_SESSION_TERM_BY_USER);
@@ -589,15 +927,17 @@
resMsg.setResultCode(confirmed ? ResultCode.OK
: ResultCode.UICC_SESSION_TERM_BY_USER);
if (confirmed) {
- launchBrowser = true;
- mBrowserSettings = mCurrentCmd.getBrowserSettings();
+ mStkContext[slotId].launchBrowser = true;
+ mStkContext[slotId].mBrowserSettings =
+ mStkContext[slotId].mCurrentCmd.getBrowserSettings();
}
break;
case SET_UP_CALL:
resMsg.setResultCode(ResultCode.OK);
resMsg.setConfirmation(confirmed);
if (confirmed) {
- launchEventMessage(mCurrentCmd.getCallSettings().callMsg);
+ launchEventMessage(slotId,
+ mStkContext[slotId].mCurrentCmd.getCallSettings().callMsg);
}
break;
}
@@ -606,22 +946,22 @@
resMsg.setResultCode(ResultCode.OK);
break;
case RES_ID_BACKWARD:
- CatLog.d(this, "RES_ID_BACKWARD");
+ CatLog.d(LOG_TAG, "RES_ID_BACKWARD");
resMsg.setResultCode(ResultCode.BACKWARD_MOVE_BY_USER);
break;
case RES_ID_END_SESSION:
- CatLog.d(this, "RES_ID_END_SESSION");
+ CatLog.d(LOG_TAG, "RES_ID_END_SESSION");
resMsg.setResultCode(ResultCode.UICC_SESSION_TERM_BY_USER);
break;
case RES_ID_TIMEOUT:
- CatLog.d(this, "RES_ID_TIMEOUT");
+ CatLog.d(LOG_TAG, "RES_ID_TIMEOUT");
// GCF test-case 27.22.4.1.1 Expected Sequence 1.5 (DISPLAY TEXT,
// Clear message after delay, successful) expects result code OK.
// If the command qualifier specifies no user response is required
// then send OK instead of NO_RESPONSE_FROM_USER
- if ((mCurrentCmd.getCmdType().value() == AppInterface.CommandType.DISPLAY_TEXT
- .value())
- && (mCurrentCmd.geTextMessage().userClear == false)) {
+ if ((mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
+ AppInterface.CommandType.DISPLAY_TEXT.value())
+ && (mStkContext[slotId].mCurrentCmd.geTextMessage().userClear == false)) {
resMsg.setResultCode(ResultCode.OK);
} else {
resMsg.setResultCode(ResultCode.NO_RESPONSE_FROM_USER);
@@ -640,17 +980,23 @@
break;
}
- if (mCurrentCmd.getCmdType().value() == AppInterface.CommandType.OPEN_CHANNEL
- .value()) {
+ if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
+ AppInterface.CommandType.OPEN_CHANNEL.value()) {
resMsg.setConfirmation(confirmed);
}
break;
default:
- CatLog.d(this, "Unknown result id");
+ CatLog.d(LOG_TAG, "Unknown result id");
return;
}
- mStkService.onCmdResponse(resMsg);
+
+ if (null != mStkContext[slotId].mCurrentCmd &&
+ null != mStkContext[slotId].mCurrentCmd.getCmdType()) {
+ CatLog.d(LOG_TAG, "handleCmdResponse- cmdName[" +
+ mStkContext[slotId].mCurrentCmd.getCmdType().name() + "]");
+ }
+ mStkService[slotId].onCmdResponse(resMsg);
}
/**
@@ -664,59 +1010,193 @@
*
* @return 0 or FLAG_ACTIVITY_NO_USER_ACTION
*/
- private int getFlagActivityNoUserAction(InitiatedByUserAction userAction) {
- return ((userAction == InitiatedByUserAction.yes) | mMenuIsVisibile) ?
- 0 : Intent.FLAG_ACTIVITY_NO_USER_ACTION;
+ private int getFlagActivityNoUserAction(InitiatedByUserAction userAction, int slotId) {
+ return ((userAction == InitiatedByUserAction.yes) | mStkContext[slotId].mMenuIsVisible)
+ ? 0 : Intent.FLAG_ACTIVITY_NO_USER_ACTION;
+ }
+ /**
+ * This method is used for cleaning up pending instances in stack.
+ */
+ private void cleanUpInstanceStackBySlot(int slotId) {
+ Activity activity = mStkContext[slotId].getPendingActivityInstance();
+ Activity dialog = mStkContext[slotId].getPendingDialogInstance();
+ CatLog.d(LOG_TAG, "cleanUpInstanceStackBySlot slotId: " + slotId);
+ if (activity != null) {
+ CatLog.d(LOG_TAG, "current cmd type: " +
+ mStkContext[slotId].mCurrentCmd.getCmdType());
+ if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
+ AppInterface.CommandType.GET_INPUT.value() ||
+ mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
+ AppInterface.CommandType.GET_INKEY.value()) {
+ mStkContext[slotId].mIsInputPending = true;
+ } else if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
+ AppInterface.CommandType.SET_UP_MENU.value() ||
+ mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
+ AppInterface.CommandType.SELECT_ITEM.value()) {
+ mStkContext[slotId].mIsMenuPending = true;
+ } else {
+ }
+ CatLog.d(LOG_TAG, "finish pending activity.");
+ activity.finish();
+ mStkContext[slotId].mActivityInstance = null;
+ }
+ if (dialog != null) {
+ CatLog.d(LOG_TAG, "finish pending dialog.");
+ mStkContext[slotId].mIsDialogPending = true;
+ dialog.finish();
+ mStkContext[slotId].mDialogInstance = null;
+ }
+ }
+ /**
+ * This method is used for restoring pending instances from stack.
+ */
+ private void restoreInstanceFromStackBySlot(int slotId) {
+ AppInterface.CommandType cmdType = mStkContext[slotId].mCurrentCmd.getCmdType();
+
+ CatLog.d(LOG_TAG, "restoreInstanceFromStackBySlot cmdType : " + cmdType);
+ switch(cmdType) {
+ case GET_INPUT:
+ case GET_INKEY:
+ launchInputActivity(slotId);
+ //Set mMenuIsVisible to true for showing main menu for
+ //following session end command.
+ mStkContext[slotId].mMenuIsVisible = true;
+ break;
+ case DISPLAY_TEXT:
+ launchTextDialog(slotId);
+ break;
+ case LAUNCH_BROWSER:
+ launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.geTextMessage(),
+ slotId);
+ break;
+ case OPEN_CHANNEL:
+ launchOpenChannelDialog(slotId);
+ break;
+ case SET_UP_CALL:
+ launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.getCallSettings().
+ confirmMsg, slotId);
+ break;
+ case SET_UP_MENU:
+ case SELECT_ITEM:
+ launchMenuActivity(null, slotId);
+ break;
+ default:
+ break;
+ }
}
- private void launchMenuActivity(Menu menu) {
+ private void launchMenuActivity(Menu menu, int slotId) {
Intent newIntent = new Intent(Intent.ACTION_VIEW);
- newIntent.setClassName(PACKAGE_NAME, MENU_ACTIVITY_NAME);
- int intentFlags = Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_CLEAR_TOP;
+ String targetActivity = STK_MENU_ACTIVITY_NAME;
+ String uriString = STK_MENU_URI + System.currentTimeMillis();
+ //Set unique URI to create a new instance of activity for different slotId.
+ Uri uriData = Uri.parse(uriString);
+
+ CatLog.d(LOG_TAG, "launchMenuActivity, slotId: " + slotId + " , " +
+ uriData.toString() + " , " + mStkContext[slotId].mOpCode + ", "
+ + mStkContext[slotId].mMenuState);
+ newIntent.setClassName(PACKAGE_NAME, targetActivity);
+ int intentFlags = Intent.FLAG_ACTIVITY_NEW_TASK;
+
if (menu == null) {
// We assume this was initiated by the user pressing the tool kit icon
- intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.yes);
+ intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.yes, slotId);
+ if (mStkContext[slotId].mOpCode == OP_END_SESSION) {
+ CatLog.d(LOG_TAG, "launchMenuActivity, return OP_END_SESSION");
+ mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
+ if (mStkContext[slotId].mMainActivityInstance != null) {
+ CatLog.d(LOG_TAG, "launchMenuActivity, mMainActivityInstance is not null");
+ return;
+ }
+ // If END SESSION is sent that results from the activity is finished by
+ // stkappservice (line 457), we should igonore to display the stk main menu
+ // of slot id.
+ if (mStkContext[slotId].mBackGroundTRSent) {
+ CatLog.d(LOG_TAG, "launchMenuActivity, ES is triggered by BG.");
+ mStkContext[slotId].mBackGroundTRSent = false;
+ return;
+ }
+ }
- newIntent.putExtra("STATE", StkMenuActivity.STATE_MAIN);
+ //If the last pending menu is secondary menu, "STATE" should be "STATE_SECONDARY".
+ //Otherwise, it should be "STATE_MAIN".
+ if (mStkContext[slotId].mOpCode == OP_LAUNCH_APP &&
+ mStkContext[slotId].mMenuState == StkMenuActivity.STATE_SECONDARY) {
+ newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
+ } else {
+ newIntent.putExtra("STATE", StkMenuActivity.STATE_MAIN);
+ mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
+ }
} else {
// We don't know and we'll let getFlagActivityNoUserAction decide.
- intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.unknown);
-
+ intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
+ mStkContext[slotId].mMenuState = StkMenuActivity.STATE_SECONDARY;
}
+ newIntent.putExtra(SLOT_ID, slotId);
+ newIntent.setData(uriData);
newIntent.setFlags(intentFlags);
mContext.startActivity(newIntent);
}
- private void launchInputActivity() {
+ private void launchInputActivity(int slotId) {
Intent newIntent = new Intent(Intent.ACTION_VIEW);
+ String targetActivity = STK_INPUT_ACTIVITY_NAME;
+ String uriString = STK_INPUT_URI + System.currentTimeMillis();
+ //Set unique URI to create a new instance of activity for different slotId.
+ Uri uriData = Uri.parse(uriString);
+
+ CatLog.d(LOG_TAG, "launchInputActivity, slotId: " + slotId);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | getFlagActivityNoUserAction(InitiatedByUserAction.unknown));
- newIntent.setClassName(PACKAGE_NAME, INPUT_ACTIVITY_NAME);
- newIntent.putExtra("INPUT", mCurrentCmd.geInput());
+ | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
+ newIntent.setClassName(PACKAGE_NAME, targetActivity);
+ newIntent.putExtra("INPUT", mStkContext[slotId].mCurrentCmd.geInput());
+ newIntent.putExtra(SLOT_ID, slotId);
+ newIntent.setData(uriData);
mContext.startActivity(newIntent);
}
- private void launchTextDialog() {
- Intent newIntent = new Intent(this, StkDialogActivity.class);
- newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_CLEAR_TOP
- | Intent.FLAG_ACTIVITY_NO_HISTORY
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | getFlagActivityNoUserAction(InitiatedByUserAction.unknown));
- newIntent.putExtra("TEXT", mCurrentCmd.geTextMessage());
- startActivity(newIntent);
+ private void launchTextDialog(int slotId) {
+ CatLog.d(LOG_TAG, "launchTextDialog, slotId: " + slotId);
+ Intent newIntent = new Intent();
+ String targetActivity = STK_DIALOG_ACTIVITY_NAME;
+ int action = getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
+ String uriString = STK_DIALOG_URI + System.currentTimeMillis();
+ //Set unique URI to create a new instance of activity for different slotId.
+ Uri uriData = Uri.parse(uriString);
+ if (newIntent != null) {
+ newIntent.setClassName(PACKAGE_NAME, targetActivity);
+ newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+ | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
+ newIntent.setData(uriData);
+ newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
+ newIntent.putExtra(SLOT_ID, slotId);
+ startActivity(newIntent);
+ }
}
- private void launchEventMessage() {
- launchEventMessage(mCurrentCmd.geTextMessage());
+ public boolean isStkDialogActivated(Context context) {
+ String stkDialogActivity = "com.android.stk.StkDialogActivity";
+ boolean activated = false;
+ final ActivityManager am = (ActivityManager) context.getSystemService(
+ Context.ACTIVITY_SERVICE);
+ String topActivity = am.getRunningTasks(1).get(0).topActivity.getClassName();
+
+ CatLog.d(LOG_TAG, "isStkDialogActivated: " + topActivity);
+ if (topActivity.equals(stkDialogActivity)) {
+ activated = true;
+ }
+ CatLog.d(LOG_TAG, "activated : " + activated);
+ return activated;
}
- private void launchEventMessage(TextMessage msg) {
- if (msg == null || msg.text == null) {
+ private void launchEventMessage(int slotId, TextMessage msg) {
+ if (msg == null || (msg.text != null && msg.text.length() == 0)) {
+ CatLog.d(LOG_TAG, "launchEventMessage return");
return;
}
+
Toast toast = new Toast(mContext.getApplicationContext());
LayoutInflater inflate = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -740,15 +1220,29 @@
toast.show();
}
- private void launchConfirmationDialog(TextMessage msg) {
- msg.title = lastSelectedItem;
- Intent newIntent = new Intent(this, StkDialogActivity.class);
- newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_NO_HISTORY
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | getFlagActivityNoUserAction(InitiatedByUserAction.unknown));
- newIntent.putExtra("TEXT", msg);
- startActivity(newIntent);
+ private void launchEventMessage(int slotId) {
+ launchEventMessage(slotId, mStkContext[slotId].mCurrentCmd.geTextMessage());
+ }
+
+ private void launchConfirmationDialog(TextMessage msg, int slotId) {
+ msg.title = mStkContext[slotId].lastSelectedItem;
+ Intent newIntent = new Intent();
+ String targetActivity = STK_DIALOG_ACTIVITY_NAME;
+ String uriString = STK_DIALOG_URI + System.currentTimeMillis();
+ //Set unique URI to create a new instance of activity for different slotId.
+ Uri uriData = Uri.parse(uriString);
+
+ if (newIntent != null) {
+ newIntent.setClassName(this, targetActivity);
+ newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_NO_HISTORY
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+ | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
+ newIntent.putExtra("TEXT", msg);
+ newIntent.putExtra(SLOT_ID, slotId);
+ newIntent.setData(uriData);
+ startActivity(newIntent);
+ }
}
private void launchBrowser(BrowserSettings settings) {
@@ -760,12 +1254,12 @@
Uri data = null;
if (settings.url != null) {
- CatLog.d(this, "settings.url = " + settings.url);
+ CatLog.d(LOG_TAG, "settings.url = " + settings.url);
if ((settings.url.startsWith("http://") || (settings.url.startsWith("https://")))) {
data = Uri.parse(settings.url);
} else {
String modifiedUrl = "http://" + settings.url;
- CatLog.d(this, "modifiedUrl = " + modifiedUrl);
+ CatLog.d(LOG_TAG, "modifiedUrl = " + modifiedUrl);
data = Uri.parse(modifiedUrl);
}
}
@@ -775,7 +1269,7 @@
} else {
// if the command did not contain a URL,
// launch the browser to the default homepage.
- CatLog.d(this, "launch browser with default URL ");
+ CatLog.d(LOG_TAG, "launch browser with default URL ");
intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN,
Intent.CATEGORY_APP_BROWSER);
}
@@ -802,24 +1296,31 @@
} catch (InterruptedException e) {}
}
- private void launchIdleText() {
- TextMessage msg = mCurrentCmd.geTextMessage();
+ private void launchIdleText(int slotId) {
+ TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
if (msg == null) {
- CatLog.d(this, "mCurrent.getTextMessage is NULL");
- mNotificationManager.cancel(STK_NOTIFICATION_ID);
+ CatLog.d(LOG_TAG, "mCurrent.getTextMessage is NULL");
+ mNotificationManager.cancel(getNotificationId(slotId));
return;
}
+ CatLog.d(LOG_TAG, "launchIdleText - text[" + msg.text
+ + "] iconSelfExplanatory[" + msg.iconSelfExplanatory
+ + "] icon[" + msg.icon + "], sim id: " + slotId);
+
if (msg.text == null) {
- mNotificationManager.cancel(STK_NOTIFICATION_ID);
+ CatLog.d(LOG_TAG, "cancel IdleMode text");
+ mNotificationManager.cancel(getNotificationId(slotId));
} else {
+ CatLog.d(LOG_TAG, "Add IdleMode text");
PendingIntent pendingIntent = PendingIntent.getService(mContext, 0,
new Intent(mContext, StkAppService.class), 0);
final Notification.Builder notificationBuilder = new Notification.Builder(
StkAppService.this);
- if (mMainCmd != null && mMainCmd.getMenu() != null) {
- notificationBuilder.setContentTitle(mMainCmd.getMenu().title);
+ if (mStkContext[slotId].mMainCmd != null &&
+ mStkContext[slotId].mMainCmd.getMenu() != null) {
+ notificationBuilder.setContentTitle(mStkContext[slotId].mMainCmd.getMenu().title);
} else {
notificationBuilder.setContentTitle("");
}
@@ -842,25 +1343,31 @@
}
notificationBuilder.setColor(mContext.getResources().getColor(
com.android.internal.R.color.system_notification_accent_color));
- mNotificationManager.notify(STK_NOTIFICATION_ID, notificationBuilder.build());
+ mNotificationManager.notify(getNotificationId(slotId), notificationBuilder.build());
}
}
- private void launchToneDialog() {
+ private void launchToneDialog(int slotId) {
Intent newIntent = new Intent(this, ToneDialog.class);
+ String uriString = STK_TONE_URI + slotId;
+ Uri uriData = Uri.parse(uriString);
+ //Set unique URI to create a new instance of activity for different slotId.
+ CatLog.d(LOG_TAG, "launchToneDialog, slotId: " + slotId);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_NO_HISTORY
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | getFlagActivityNoUserAction(InitiatedByUserAction.unknown));
- newIntent.putExtra("TEXT", mCurrentCmd.geTextMessage());
- newIntent.putExtra("TONE", mCurrentCmd.getToneSettings());
+ | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
+ newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
+ newIntent.putExtra("TONE", mStkContext[slotId].mCurrentCmd.getToneSettings());
+ newIntent.putExtra(SLOT_ID, slotId);
+ newIntent.setData(uriData);
startActivity(newIntent);
}
- private void launchOpenChannelDialog() {
- TextMessage msg = mCurrentCmd.geTextMessage();
+ private void launchOpenChannelDialog(int slotId) {
+ TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
if (msg == null) {
- CatLog.d(this, "msg is null, return here");
+ CatLog.d(LOG_TAG, "msg is null, return here");
return;
}
@@ -909,10 +1416,10 @@
dialog.show();
}
- private void launchTransientEventMessage() {
- TextMessage msg = mCurrentCmd.geTextMessage();
+ private void launchTransientEventMessage(int slotId) {
+ TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
if (msg == null) {
- CatLog.d(this, "msg is null, return here");
+ CatLog.d(LOG_TAG, "msg is null, return here");
return;
}
@@ -939,8 +1446,19 @@
dialog.show();
}
- private String getItemName(int itemId) {
- Menu menu = mCurrentCmd.getMenu();
+ private int getNotificationId(int slotId) {
+ int notifyId = STK_NOTIFICATION_ID;
+ if (slotId >= 0 && slotId < mSimCount) {
+ notifyId += slotId;
+ } else {
+ CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
+ }
+ CatLog.d(LOG_TAG, "getNotificationId, slotId: " + slotId + ", notifyId: " + notifyId);
+ return notifyId;
+ }
+
+ private String getItemName(int itemId, int slotId) {
+ Menu menu = mStkContext[slotId].mCurrentCmd.getMenu();
if (menu == null) {
return null;
}
@@ -952,16 +1470,27 @@
return null;
}
- private boolean removeMenu() {
+ private boolean removeMenu(int slotId) {
try {
- if (mCurrentMenu.items.size() == 1 &&
- mCurrentMenu.items.get(0) == null) {
+ if (mStkContext[slotId].mCurrentMenu.items.size() == 1 &&
+ mStkContext[slotId].mCurrentMenu.items.get(0) == null) {
+ mStkContext[slotId].mSetupMenuState = STATE_NOT_EXIST;
return true;
}
} catch (NullPointerException e) {
- CatLog.d(this, "Unable to get Menu's items size");
+ CatLog.d(LOG_TAG, "Unable to get Menu's items size");
+ mStkContext[slotId].mSetupMenuState = STATE_NOT_EXIST;
return true;
}
+ mStkContext[slotId].mSetupMenuState = STATE_EXIST;
return false;
}
+ StkContext getStkContext(int slotId) {
+ if (slotId >= 0 && slotId < mSimCount) {
+ return mStkContext[slotId];
+ } else {
+ CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
+ return null;
+ }
+ }
}
diff --git a/src/com/android/stk/StkCmdReceiver.java b/src/com/android/stk/StkCmdReceiver.java
index 8e9aae7..254c7fb 100644
--- a/src/com/android/stk/StkCmdReceiver.java
+++ b/src/com/android/stk/StkCmdReceiver.java
@@ -18,12 +18,14 @@
import com.android.internal.telephony.cat.AppInterface;
import com.android.internal.telephony.uicc.IccRefreshResponse;
-
+import com.android.internal.telephony.cat.CatLog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import com.android.internal.telephony.cat.AppInterface;
+
/**
* Receiver class to get STK intents, broadcasted by telephony layer.
*
@@ -35,45 +37,42 @@
String action = intent.getAction();
if (action.equals(AppInterface.CAT_CMD_ACTION)) {
- handleCommandMessage(context, intent);
+ handleAction(context, intent, StkAppService.OP_CMD);
} else if (action.equals(AppInterface.CAT_SESSION_END_ACTION)) {
- handleSessionEnd(context, intent);
+ handleAction(context, intent, StkAppService.OP_END_SESSION);
} else if (action.equals(AppInterface.CAT_ICC_STATUS_CHANGE)) {
- handleCardStatusChange(context, intent);
+ handleAction(context, intent, StkAppService.OP_CARD_STATUS_CHANGED);
}
}
- private void handleCommandMessage(Context context, Intent intent) {
+ private void handleAction(Context context, Intent intent, int op) {
Bundle args = new Bundle();
- args.putInt(StkAppService.OPCODE, StkAppService.OP_CMD);
- args.putParcelable(StkAppService.CMD_MSG, intent
- .getParcelableExtra("STK CMD"));
- context.startService(new Intent(context, StkAppService.class)
- .putExtras(args));
- }
+ int slot_id = intent.getIntExtra(StkAppService.SLOT_ID,0);
- private void handleSessionEnd(Context context, Intent intent) {
- Bundle args = new Bundle();
- args.putInt(StkAppService.OPCODE, StkAppService.OP_END_SESSION);
- context.startService(new Intent(context, StkAppService.class)
- .putExtras(args));
- }
+ args.putInt(StkAppService.OPCODE, op);
+ args.putInt(StkAppService.SLOT_ID, slot_id);
- private void handleCardStatusChange(Context context, Intent intent) {
- // If the Card is absent then check if the StkAppService is even
- // running before starting it to stop it right away
- if ((intent.getBooleanExtra(AppInterface.CARD_STATUS, false) == false)
- && StkAppService.getInstance() == null) {
- return;
+ if (StkAppService.OP_CMD == op) {
+ args.putParcelable(StkAppService.CMD_MSG, intent
+ .getParcelableExtra(StkAppService.STK_CMD));
+ } else if (StkAppService.OP_CARD_STATUS_CHANGED == op) {
+ // If the Card is absent then check if the StkAppService is even
+ // running before starting it to stop it right away
+ if ((intent.getBooleanExtra(AppInterface.CARD_STATUS, false) == false)
+ && StkAppService.getInstance() == null) {
+ return;
+ }
+
+ args.putBoolean(AppInterface.CARD_STATUS,
+ intent.getBooleanExtra(AppInterface.CARD_STATUS, true));
+ args.putInt(AppInterface.REFRESH_RESULT,
+ intent.getIntExtra(AppInterface.REFRESH_RESULT,
+ IccRefreshResponse.REFRESH_RESULT_FILE_UPDATE));
}
- Bundle args = new Bundle();
- args.putInt(StkAppService.OPCODE, StkAppService.OP_CARD_STATUS_CHANGED);
- args.putBoolean(AppInterface.CARD_STATUS,
- intent.getBooleanExtra(AppInterface.CARD_STATUS, true));
- args.putInt(AppInterface.REFRESH_RESULT,
- intent.getIntExtra(AppInterface.REFRESH_RESULT,
- IccRefreshResponse.REFRESH_RESULT_FILE_UPDATE));
- context.startService(new Intent(context, StkAppService.class)
- .putExtras(args));
+ CatLog.d("StkCmdReceiver", "handleAction, op: " + op +
+ "args: " + args + ", slot id: " + slot_id);
+ Intent toService = new Intent(context, StkAppService.class);
+ toService.putExtras(args);
+ context.startService(toService);
}
}
diff --git a/src/com/android/stk/StkDialogActivity.java b/src/com/android/stk/StkDialogActivity.java
old mode 100644
new mode 100755
index cf81f03..b09aa40
--- a/src/com/android/stk/StkDialogActivity.java
+++ b/src/com/android/stk/StkDialogActivity.java
@@ -37,14 +37,19 @@
*/
public class StkDialogActivity extends Activity implements View.OnClickListener {
// members
- TextMessage mTextMsg;
-
+ private static final String className = new Object(){}.getClass().getEnclosingClass().getName();
+ private static final String LOG_TAG = className.substring(className.lastIndexOf('.') + 1);
+ TextMessage mTextMsg = null;
+ private int mSlotId = -1;
+ private StkAppService appService = StkAppService.getInstance();
private boolean mIsResponseSent = false;
+
Handler mTimeoutHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
case MSG_ID_TIMEOUT:
+ CatLog.d(LOG_TAG, "MSG_ID_TIMEOUT finish.");
sendResponse(StkAppService.RES_ID_TIMEOUT);
finish();
break;
@@ -66,6 +71,7 @@
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ CatLog.d(LOG_TAG, "onCreate");
initFromIntent(getIntent());
if (mTextMsg == null) {
finish();
@@ -91,6 +97,7 @@
}
if (mTextMsg.icon == null) {
+ CatLog.d(LOG_TAG, "onCreate icon is null");
window.setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
com.android.internal.R.drawable.stat_notify_sim_toolkit);
} else {
@@ -104,11 +111,15 @@
switch (v.getId()) {
case OK_BUTTON:
+ CatLog.d(LOG_TAG, "OK Clicked!, mSlotId: " + mSlotId);
sendResponse(StkAppService.RES_ID_CONFIRM, true);
+ cancelTimeOut();
finish();
break;
case CANCEL_BUTTON:
+ CatLog.d(LOG_TAG, "Cancel Clicked!, mSlotId: " + mSlotId);
sendResponse(StkAppService.RES_ID_CONFIRM, false);
+ cancelTimeOut();
finish();
break;
}
@@ -118,6 +129,8 @@
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
+ CatLog.d(LOG_TAG, "onKeyDown - KEYCODE_BACK");
+ cancelTimeOut();
sendResponse(StkAppService.RES_ID_BACKWARD);
finish();
break;
@@ -128,7 +141,8 @@
@Override
public void onResume() {
super.onResume();
-
+ CatLog.d(LOG_TAG, "onResume - mIsResponseSent[" + mIsResponseSent +
+ "], sim id: " + mSlotId);
/*
* The user should be shown the message forever or until some high
* priority event occurs (such as incoming call, MMI code execution
@@ -151,7 +165,7 @@
@Override
public void onPause() {
super.onPause();
-
+ CatLog.d(LOG_TAG, "onPause, sim id: " + mSlotId);
cancelTimeOut();
}
@@ -164,13 +178,37 @@
@Override
public void onStop() {
super.onStop();
+ CatLog.d(LOG_TAG, "onStop - before Send CONFIRM false mIsResponseSent[" +
+ mIsResponseSent + "], sim id: " + mSlotId);
if (!mIsResponseSent) {
- sendResponse(StkAppService.RES_ID_TIMEOUT);
+ appService.getStkContext(mSlotId).setPendingDialogInstance(this);
+ } else {
+ CatLog.d(LOG_TAG, "finish.");
+ appService.getStkContext(mSlotId).setPendingDialogInstance(null);
+ cancelTimeOut();
+ finish();
+ CatLog.d(LOG_TAG, "finish.");
}
}
@Override
+ public void onDestroy() {
+ super.onDestroy();
+ CatLog.d(LOG_TAG, "onDestroy - mIsResponseSent[" + mIsResponseSent +
+ "], sim id: " + mSlotId);
+ // if dialog activity is finished by stkappservice
+ // when receiving OP_LAUNCH_APP from the other SIM, we can not send TR here
+ // , since the dialog cmd is waiting user to process.
+ if (!mIsResponseSent && !appService.isDialogPending(mSlotId)) {
+ sendResponse(StkAppService.RES_ID_CONFIRM, false);
+ }
+ cancelTimeOut();
+ }
+
+ @Override
public void onSaveInstanceState(Bundle outState) {
+ CatLog.d(LOG_TAG, "onSaveInstanceState");
+
super.onSaveInstanceState(outState);
outState.putParcelable(TEXT, mTextMsg);
@@ -181,11 +219,25 @@
super.onRestoreInstanceState(savedInstanceState);
mTextMsg = savedInstanceState.getParcelable(TEXT);
+ CatLog.d(LOG_TAG, "onRestoreInstanceState - [" + mTextMsg + "]");
}
private void sendResponse(int resId, boolean confirmed) {
+ if (mSlotId == -1) {
+ CatLog.d(LOG_TAG, "sim id is invalid");
+ return;
+ }
+
+ if (StkAppService.getInstance() == null) {
+ CatLog.d(LOG_TAG, "Ignore response: id is " + resId);
+ return;
+ }
+
+ CatLog.d(LOG_TAG, "sendResponse resID[" + resId + "] confirmed[" + confirmed + "]");
+
Bundle args = new Bundle();
args.putInt(StkAppService.OPCODE, StkAppService.OP_RESPONSE);
+ args.putInt(StkAppService.SLOT_ID, mSlotId);
args.putInt(StkAppService.RES_ID, resId);
args.putBoolean(StkAppService.CONFIRMATION, confirmed);
startService(new Intent(this, StkAppService.class).putExtras(args));
@@ -200,12 +252,16 @@
if (intent != null) {
mTextMsg = intent.getParcelableExtra("TEXT");
+ mSlotId = intent.getIntExtra(StkAppService.SLOT_ID, -1);
} else {
finish();
}
+
+ CatLog.d(LOG_TAG, "initFromIntent - [" + mTextMsg + "], sim id: " + mSlotId);
}
private void cancelTimeOut() {
+ CatLog.d(LOG_TAG, "cancelTimeOut: " + mSlotId);
mTimeoutHandler.removeMessages(MSG_ID_TIMEOUT);
}
@@ -215,14 +271,20 @@
int dialogDuration = StkApp.calculateDurationInMilis(mTextMsg.duration);
// If duration is specified, this has priority. If not, set timeout
// according to condition given by the card.
- if (dialogDuration == 0) {
- if (waitForUserToClear) {
- dialogDuration = StkApp.DISP_TEXT_WAIT_FOR_USER_TIMEOUT;
- } else {
- dialogDuration = StkApp.DISP_TEXT_CLEAR_AFTER_DELAY_TIMEOUT;
+ if (mTextMsg.userClear == true && mTextMsg.responseNeeded == false) {
+ return;
+ } else {
+ // userClear = false. will dissapear after a while.
+ if (dialogDuration == 0) {
+ if (waitForUserToClear) {
+ dialogDuration = StkApp.DISP_TEXT_WAIT_FOR_USER_TIMEOUT;
+ } else {
+ dialogDuration = StkApp.DISP_TEXT_CLEAR_AFTER_DELAY_TIMEOUT;
+ }
}
- }
- mTimeoutHandler.sendMessageDelayed(mTimeoutHandler
+ CatLog.d(LOG_TAG, "startTimeOut: " + mSlotId);
+ mTimeoutHandler.sendMessageDelayed(mTimeoutHandler
.obtainMessage(MSG_ID_TIMEOUT), dialogDuration);
+ }
}
}
diff --git a/src/com/android/stk/StkInputActivity.java b/src/com/android/stk/StkInputActivity.java
old mode 100644
new mode 100755
index eb66a32..bfaa36d
--- a/src/com/android/stk/StkInputActivity.java
+++ b/src/com/android/stk/StkInputActivity.java
@@ -36,7 +36,7 @@
import android.widget.TextView;
import android.widget.EditText;
import android.widget.TextView.BufferType;
-
+import com.android.internal.telephony.cat.CatLog;
import com.android.internal.telephony.cat.FontSize;
import com.android.internal.telephony.cat.Input;
@@ -53,9 +53,14 @@
private TextView mPromptView = null;
private View mYesNoLayout = null;
private View mNormalLayout = null;
- private Input mStkInput = null;
// Constants
+ private static final String className = new Object(){}.getClass().getEnclosingClass().getName();
+ private static final String LOG_TAG = className.substring(className.lastIndexOf('.') + 1);
+
+ private Input mStkInput = null;
+ private boolean mAcceptUsersInput = true;
+ // Constants
private static final int STATE_TEXT = 1;
private static final int STATE_YES_NO = 2;
@@ -69,15 +74,21 @@
// message id for time out
private static final int MSG_ID_TIMEOUT = 1;
+ private StkAppService appService = StkAppService.getInstance();
+
+ private boolean mIsResponseSent = false;
+ private int mSlotId = -1;
+ Activity mInstance = null;
Handler mTimeoutHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
case MSG_ID_TIMEOUT:
- //mAcceptUsersInput = false;
+ CatLog.d(LOG_TAG, "Msg timeout.");
+ mAcceptUsersInput = false;
+ appService.getStkContext(mSlotId).setPendingActivityInstance(mInstance);
sendResponse(StkAppService.RES_ID_TIMEOUT);
- finish();
break;
}
}
@@ -86,39 +97,50 @@
// Click listener to handle buttons press..
public void onClick(View v) {
String input = null;
+ if (!mAcceptUsersInput) {
+ CatLog.d(LOG_TAG, "mAcceptUsersInput:false");
+ return;
+ }
switch (v.getId()) {
case R.id.button_ok:
// Check that text entered is valid .
if (!verfiyTypedText()) {
+ CatLog.d(LOG_TAG, "handleClick, invalid text");
return;
}
+ mAcceptUsersInput = false;
input = mTextIn.getText().toString();
break;
// Yes/No layout buttons.
case R.id.button_yes:
+ mAcceptUsersInput = false;
input = YES_STR_RESPONSE;
break;
case R.id.button_no:
+ mAcceptUsersInput = false;
input = NO_STR_RESPONSE;
break;
}
-
+ CatLog.d(LOG_TAG, "handleClick, ready to response");
+ appService.getStkContext(mSlotId).setPendingActivityInstance(this);
sendResponse(StkAppService.RES_ID_INPUT, input, false);
- finish();
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ CatLog.d(LOG_TAG, "onCreate - mIsResponseSent[" + mIsResponseSent + "]");
+
// Set the layout for this activity.
+ requestWindowFeature(Window.FEATURE_LEFT_ICON);
setContentView(R.layout.stk_input);
// Initialize members
mTextIn = (EditText) this.findViewById(R.id.in_text);
mPromptView = (TextView) this.findViewById(R.id.prompt);
-
+ mInstance = this;
// Set buttons listeners.
Button okButton = (Button) findViewById(R.id.button_ok);
Button yesButton = (Button) findViewById(R.id.button_yes);
@@ -130,22 +152,9 @@
mYesNoLayout = findViewById(R.id.yes_no_layout);
mNormalLayout = findViewById(R.id.normal_layout);
-
- // Get the calling intent type: text/key, and setup the
- // display parameters.
- Intent intent = getIntent();
- if (intent != null) {
- mStkInput = intent.getParcelableExtra("INPUT");
- if (mStkInput == null) {
- finish();
- } else {
- mState = mStkInput.yesNo ? STATE_YES_NO : STATE_TEXT;
- configInputDisplay();
- }
- } else {
- finish();
- }
+ initFromIntent(getIntent());
mContext = getBaseContext();
+ mAcceptUsersInput = true;
}
@Override
@@ -158,35 +167,84 @@
@Override
public void onResume() {
super.onResume();
-
+ CatLog.d(LOG_TAG, "onResume - mIsResponseSent[" + mIsResponseSent +
+ "], slot id: " + mSlotId);
startTimeOut();
+ appService.getStkContext(mSlotId).setPendingActivityInstance(null);
}
@Override
public void onPause() {
super.onPause();
+ CatLog.d(LOG_TAG, "onPause - mIsResponseSent[" + mIsResponseSent + "]");
+ }
+ @Override
+ public void onStop() {
+ super.onStop();
+ CatLog.d(LOG_TAG, "onStop - mIsResponseSent[" + mIsResponseSent + "]");
+ if (mIsResponseSent) {
+ cancelTimeOut();
+ finish();
+ } else {
+ appService.getStkContext(mSlotId).setPendingActivityInstance(this);
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ CatLog.d(LOG_TAG, "onDestroy - before Send End Session mIsResponseSent[" +
+ mIsResponseSent + " , " + mSlotId + "]");
+ //If the input activity is finished by stkappservice
+ //when receiving OP_LAUNCH_APP from the other SIM, we can not send TR here
+ //, since the input cmd is waiting user to process.
+ if (!mIsResponseSent && !appService.isInputPending(mSlotId)) {
+ CatLog.d(LOG_TAG, "handleDestroy - Send End Session");
+ sendResponse(StkAppService.RES_ID_END_SESSION);
+ }
cancelTimeOut();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (!mAcceptUsersInput) {
+ CatLog.d(LOG_TAG, "mAcceptUsersInput:false");
+ return true;
+ }
+
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
+ CatLog.d(LOG_TAG, "onKeyDown - KEYCODE_BACK");
+ mAcceptUsersInput = false;
+ appService.getStkContext(mSlotId).setPendingActivityInstance(this);
sendResponse(StkAppService.RES_ID_BACKWARD, null, false);
- finish();
- break;
+ return true;
}
return super.onKeyDown(keyCode, event);
}
- private void sendResponse(int resId) {
+ void sendResponse(int resId) {
sendResponse(resId, null, false);
}
- private void sendResponse(int resId, String input, boolean help) {
+ void sendResponse(int resId, String input, boolean help) {
+ if (mSlotId == -1) {
+ CatLog.d(LOG_TAG, "slot id is invalid");
+ return;
+ }
+
+ if (StkAppService.getInstance() == null) {
+ CatLog.d(LOG_TAG, "StkAppService is null, Ignore response: id is " + resId);
+ return;
+ }
+
+ CatLog.d(LOG_TAG, "sendResponse resID[" + resId + "] input[" + input +
+ "] help[" + help + "]");
+ mIsResponseSent = true;
Bundle args = new Bundle();
args.putInt(StkAppService.OPCODE, StkAppService.OP_RESPONSE);
+ args.putInt(StkAppService.SLOT_ID, mSlotId);
args.putInt(StkAppService.RES_ID, resId);
if (input != null) {
args.putString(StkAppService.INPUT, input);
@@ -217,12 +275,20 @@
@Override
public boolean onOptionsItemSelected(MenuItem item) {
+ if (!mAcceptUsersInput) {
+ CatLog.d(LOG_TAG, "mAcceptUsersInput:false");
+ return true;
+ }
switch (item.getItemId()) {
case StkApp.MENU_ID_END_SESSION:
+ mAcceptUsersInput = false;
+ cancelTimeOut();
sendResponse(StkAppService.RES_ID_END_SESSION);
finish();
return true;
case StkApp.MENU_ID_HELP:
+ mAcceptUsersInput = false;
+ cancelTimeOut();
sendResponse(StkAppService.RES_ID_INPUT, "", true);
finish();
return true;
@@ -230,6 +296,18 @@
return super.onOptionsItemSelected(item);
}
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ CatLog.d(LOG_TAG, "onSaveInstanceState: " + mSlotId);
+ outState.putBoolean("ACCEPT_USERS_INPUT", mAcceptUsersInput);
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle savedInstanceState) {
+ CatLog.d(LOG_TAG, "onRestoreInstanceState: " + mSlotId);
+ mAcceptUsersInput = savedInstanceState.getBoolean("ACCEPT_USERS_INPUT");
+ }
+
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@@ -329,4 +407,24 @@
return fontSizes[size.ordinal()];
}
+
+ private void initFromIntent(Intent intent) {
+ // Get the calling intent type: text/key, and setup the
+ // display parameters.
+ CatLog.d(LOG_TAG, "initFromIntent - slot id: " + mSlotId);
+ if (intent != null) {
+ mStkInput = intent.getParcelableExtra("INPUT");
+ mSlotId = intent.getIntExtra(StkAppService.SLOT_ID, -1);
+ CatLog.d(LOG_TAG, "onCreate - slot id: " + mSlotId);
+ if (mStkInput == null) {
+ finish();
+ } else {
+ mState = mStkInput.yesNo ? STATE_YES_NO :
+ STATE_TEXT;
+ configInputDisplay();
+ }
+ } else {
+ finish();
+ }
+ }
}
diff --git a/src/com/android/stk/StkLauncherActivity.java b/src/com/android/stk/StkLauncherActivity.java
old mode 100644
new mode 100755
index 194870e..9066c3e
--- a/src/com/android/stk/StkLauncherActivity.java
+++ b/src/com/android/stk/StkLauncherActivity.java
@@ -16,24 +16,222 @@
package com.android.stk;
-import android.app.Activity;
+import android.app.ListActivity;
+import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import android.view.View;
+import android.view.KeyEvent;
+import android.view.Window;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+import com.android.internal.telephony.cat.Item;
+import com.android.internal.telephony.cat.Menu;
+import com.android.internal.telephony.cat.CatLog;
+import com.android.internal.telephony.PhoneConstants;
+
+import android.telephony.TelephonyManager;
+
+import java.util.ArrayList;
/**
* Launcher class. Serve as the app's MAIN activity, send an intent to the
* StkAppService and finish.
*
*/
-public class StkLauncherActivity extends Activity {
+public class StkLauncherActivity extends ListActivity {
+ private TextView mTitleTextView = null;
+ private ImageView mTitleIconView = null;
+ private static final String className = new Object(){}.getClass().getEnclosingClass().getName();
+ private static final String LOG_TAG = className.substring(className.lastIndexOf('.') + 1);
+ private ArrayList<Item> mStkMenuList = null;
+ private int mSingleSimId = -1;
+ private Context mContext = null;
+ private TelephonyManager mTm = null;
+ private Bitmap mBitMap = null;
+ private boolean mAcceptUsersInput = true;
+
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ CatLog.d(LOG_TAG, "onCreate+");
+ mContext = getBaseContext();
+ mTm = (TelephonyManager) mContext.getSystemService(
+ Context.TELEPHONY_SERVICE);
+ //Check if needs to show the menu list.
+ if (isShowSTKListMenu()) {
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ setContentView(R.layout.stk_menu_list);
+ mTitleTextView = (TextView) findViewById(R.id.title_text);
+ mTitleIconView = (ImageView) findViewById(R.id.title_icon);
+ mTitleTextView.setText(R.string.app_name);
+ mBitMap = BitmapFactory.decodeResource(getResources(),
+ R.drawable.ic_launcher_sim_toolkit);
+ } else {
+ //launch stk menu activity for the SIM.
+ if (mSingleSimId < 0) {
+ finish();
+ }
+ }
+ }
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ super.onListItemClick(l, v, position, id);
+ if (!mAcceptUsersInput) {
+ CatLog.d(LOG_TAG, "mAcceptUsersInput:false");
+ return;
+ }
+ int simCount = TelephonyManager.from(mContext).getSimCount();
+ Item item = getSelectedItem(position);
+ if (item == null) {
+ CatLog.d(LOG_TAG, "Item is null");
+ return;
+ }
+ CatLog.d(LOG_TAG, "launch stk menu id: " + item.id);
+ if (item.id >= PhoneConstants.SIM_ID_1 && item.id < simCount) {
+ mAcceptUsersInput = false;
+ launchSTKMainMenu(item.id);
+ }
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ CatLog.d(LOG_TAG, "mAcceptUsersInput: " + mAcceptUsersInput);
+ if (!mAcceptUsersInput) {
+ return true;
+ }
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_BACK:
+ CatLog.d(LOG_TAG, "KEYCODE_BACK.");
+ mAcceptUsersInput = false;
+ finish();
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ CatLog.d(LOG_TAG, "onResume");
+ mAcceptUsersInput = true;
+ int itemSize = addStkMenuListItems();
+ if (itemSize == 0) {
+ CatLog.d(LOG_TAG, "item size = 0 so finish.");
+ finish();
+ } else if (itemSize == 1) {
+ launchSTKMainMenu(mSingleSimId);
+ finish();
+ } else {
+ CatLog.d(LOG_TAG, "resume to show multiple stk list.");
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ CatLog.d(LOG_TAG, "onPause");
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ CatLog.d(LOG_TAG, "onDestroy");
+ }
+
+ private Item getSelectedItem(int position) {
+ Item item = null;
+ if (mStkMenuList != null) {
+ try {
+ item = mStkMenuList.get(position);
+ } catch (IndexOutOfBoundsException e) {
+ if (StkApp.DBG) {
+ CatLog.d(LOG_TAG, "IOOBE Invalid menu");
+ }
+ } catch (NullPointerException e) {
+ if (StkApp.DBG) {
+ CatLog.d(LOG_TAG, "NPE Invalid menu");
+ }
+ }
+ }
+ return item;
+ }
+
+ private int addStkMenuListItems() {
+ String appName = mContext.getResources().getString(R.string.app_name);
+ String stkItemName = null;
+ int simCount = TelephonyManager.from(mContext).getSimCount();
+ mStkMenuList = new ArrayList<Item>();
+
+ CatLog.d(LOG_TAG, "simCount: " + simCount);
+ for (int i = 0; i < simCount; i++) {
+ //Check if the card is inserted.
+ if (mTm.hasIccCard(i)) {
+ CatLog.d(LOG_TAG, "SIM " + i + " add to menu.");
+ mSingleSimId = i;
+ stkItemName = new StringBuilder(appName).append(" ")
+ .append(Integer.toString(i + 1)).toString();
+ Item item = new Item(i + 1, stkItemName, mBitMap);
+ item.id = i;
+ mStkMenuList.add(item);
+ } else {
+ CatLog.d(LOG_TAG, "SIM " + i + " is not inserted.");
+ }
+ }
+ if (mStkMenuList != null && mStkMenuList.size() > 0) {
+ if (mStkMenuList.size() > 1) {
+ StkMenuAdapter adapter = new StkMenuAdapter(this,
+ mStkMenuList, false);
+ // Bind menu list to the new adapter.
+ this.setListAdapter(adapter);
+ }
+ return mStkMenuList.size();
+ } else {
+ CatLog.d(LOG_TAG, "No stk menu item add.");
+ return 0;
+ }
+ }
+ private boolean isShowSTKListMenu() {
+ int simCount = TelephonyManager.from(mContext).getSimCount();
+ int simInsertedCount = 0;
+ int insertedSlotId = -1;
+
+ CatLog.d(LOG_TAG, "simCount: " + simCount);
+ for (int i = 0; i < simCount; i++) {
+ //Check if the card is inserted.
+ if (mTm.hasIccCard(i)) {
+ CatLog.d(LOG_TAG, "SIM " + i + " is inserted.");
+ mSingleSimId = i;
+ simInsertedCount++;
+ } else {
+ CatLog.d(LOG_TAG, "SIM " + i + " is not inserted.");
+ }
+ }
+ if (simInsertedCount > 1) {
+ return true;
+ } else {
+ //No card or only one card.
+ CatLog.d(LOG_TAG, "do not show stk list menu.");
+ return false;
+ }
+ }
+ private void launchSTKMainMenu(int slodId) {
Bundle args = new Bundle();
+ CatLog.d(LOG_TAG, "launchSTKMainMenu.");
args.putInt(StkAppService.OPCODE, StkAppService.OP_LAUNCH_APP);
- startService(new Intent(this, StkAppService.class).putExtras(args));
-
- finish();
+ args.putInt(StkAppService.SLOT_ID
+ , PhoneConstants.SIM_ID_1 + slodId);
+ startService(new Intent(this, StkAppService.class)
+ .putExtras(args));
}
}
diff --git a/src/com/android/stk/StkMenuActivity.java b/src/com/android/stk/StkMenuActivity.java
old mode 100644
new mode 100755
index 93053f3..9d307f6
--- a/src/com/android/stk/StkMenuActivity.java
+++ b/src/com/android/stk/StkMenuActivity.java
@@ -17,6 +17,7 @@
package com.android.stk;
import android.app.ListActivity;
+import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@@ -37,6 +38,7 @@
import com.android.internal.telephony.cat.Item;
import com.android.internal.telephony.cat.Menu;
import com.android.internal.telephony.cat.CatLog;
+import android.telephony.TelephonyManager;
/**
* ListActivity used for displaying STK menus. These can be SET UP MENU and
@@ -49,17 +51,28 @@
private Menu mStkMenu = null;
private int mState = STATE_MAIN;
private boolean mAcceptUsersInput = true;
+ private int mSlotId = -1;
+ private boolean mIsResponseSent = false;
+ Activity mInstance = null;
private TextView mTitleTextView = null;
private ImageView mTitleIconView = null;
private ProgressBar mProgressView = null;
+ private static final String className = new Object(){}.getClass().getEnclosingClass().getName();
+ private static final String LOG_TAG = className.substring(className.lastIndexOf('.') + 1);
- StkAppService appService = StkAppService.getInstance();
+ private StkAppService appService = StkAppService.getInstance();
// Internal state values
+ static final int STATE_INIT = 0;
static final int STATE_MAIN = 1;
static final int STATE_SECONDARY = 2;
+ // Finish result
+ static final int FINISH_CAUSE_NORMAL = 1;
+ static final int FINISH_CAUSE_NULL_SERVICE = 2;
+ static final int FINISH_CAUSE_NULL_MENU = 3;
+
// message id for time out
private static final int MSG_ID_TIMEOUT = 1;
private static final int CONTEXT_MENU_HELP = 0;
@@ -69,8 +82,13 @@
public void handleMessage(Message msg) {
switch(msg.what) {
case MSG_ID_TIMEOUT:
+ CatLog.d(LOG_TAG, "MSG_ID_TIMEOUT mState: " + mState);
mAcceptUsersInput = false;
+ if (mState == STATE_SECONDARY) {
+ appService.getStkContext(mSlotId).setPendingActivityInstance(mInstance);
+ }
sendResponse(StkAppService.RES_ID_TIMEOUT);
+ //finish();//We wait the following commands to trigger onStop of this activity.
break;
}
}
@@ -80,28 +98,19 @@
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- CatLog.d(this, "onCreate");
+ CatLog.d(LOG_TAG, "onCreate");
+ // Remove the default title, customized one is used.
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
// Set the layout for this activity.
setContentView(R.layout.stk_menu_list);
-
+ mInstance = this;
mTitleTextView = (TextView) findViewById(R.id.title_text);
mTitleIconView = (ImageView) findViewById(R.id.title_icon);
mProgressView = (ProgressBar) findViewById(R.id.progress_bar);
mContext = getBaseContext();
-
- initFromIntent(getIntent());
mAcceptUsersInput = true;
-
getListView().setOnCreateContextMenuListener(this);
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
-
- CatLog.d(this, "onNewIntent");
- initFromIntent(intent);
- mAcceptUsersInput = true;
+ initFromIntent(getIntent());
}
@Override
@@ -109,13 +118,20 @@
super.onListItemClick(l, v, position, id);
if (!mAcceptUsersInput) {
+ CatLog.d(LOG_TAG, "mAcceptUsersInput:false");
return;
}
Item item = getSelectedItem(position);
if (item == null) {
+ CatLog.d(LOG_TAG, "Item is null");
return;
}
+ CatLog.d(LOG_TAG, "onListItemClick Id: " + item.id + ", mState: " + mState);
+ // ONLY set SECONDARY menu. It will be finished when the following command is comming.
+ if (mState == STATE_SECONDARY) {
+ appService.getStkContext(mSlotId).setPendingActivityInstance(this);
+ }
sendResponse(StkAppService.RES_ID_MENU_SELECTION, item.id, false);
mAcceptUsersInput = false;
mProgressView.setVisibility(View.VISIBLE);
@@ -124,21 +140,28 @@
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
-
+ CatLog.d(LOG_TAG, "mAcceptUsersInput: " + mAcceptUsersInput);
if (!mAcceptUsersInput) {
return true;
}
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
+ CatLog.d(LOG_TAG, "KEYCODE_BACK - mState[" + mState + "]");
switch (mState) {
case STATE_SECONDARY:
+ CatLog.d(LOG_TAG, "STATE_SECONDARY");
cancelTimeOut();
mAcceptUsersInput = false;
+ appService.getStkContext(mSlotId).setPendingActivityInstance(this);
sendResponse(StkAppService.RES_ID_BACKWARD);
return true;
case STATE_MAIN:
- break;
+ CatLog.d(LOG_TAG, "STATE_MAIN");
+ appService.getStkContext(mSlotId).setMainActivityInstance(null);
+ cancelTimeOut();
+ finish();
+ return true;
}
break;
}
@@ -146,25 +169,45 @@
}
@Override
+ public void onRestart() {
+ super.onRestart();
+ CatLog.d(LOG_TAG, "onRestart, slot id: " + mSlotId);
+ }
+
+ @Override
public void onResume() {
super.onResume();
- appService.indicateMenuVisibility(true);
- mStkMenu = appService.getMenu();
+ CatLog.d(LOG_TAG, "onResume, slot id: " + mSlotId + "," + mState);
+ appService.indicateMenuVisibility(true, mSlotId);
+ if (mState == STATE_MAIN) {
+ mStkMenu = appService.getMainMenu(mSlotId);
+ } else {
+ mStkMenu = appService.getMenu(mSlotId);
+ }
if (mStkMenu == null) {
+ CatLog.d(LOG_TAG, "menu is null");
+ cancelTimeOut();
finish();
return;
}
+ //Set main menu instance here for clean up stack by other SIMs
+ //when receiving OP_LAUNCH_APP.
+ if (mState == STATE_MAIN) {
+ CatLog.d(LOG_TAG, "set main menu instance.");
+ appService.getStkContext(mSlotId).setMainActivityInstance(this);
+ }
displayMenu();
startTimeOut();
// whenever this activity is resumed after a sub activity was invoked
// (Browser, In call screen) switch back to main state and enable
// user's input;
if (!mAcceptUsersInput) {
- mState = STATE_MAIN;
+ //Remove set mState to STATE_MAIN. This is for single instance flow.
mAcceptUsersInput = true;
}
invalidateOptionsMenu();
+
// make sure the progress bar is not shown.
mProgressView.setIndeterminate(false);
mProgressView.setVisibility(View.GONE);
@@ -173,17 +216,63 @@
@Override
public void onPause() {
super.onPause();
-
- appService.indicateMenuVisibility(false);
+ CatLog.d(LOG_TAG, "onPause, slot id: " + mSlotId + "," + mState);
+ //If activity is finished in onResume and it reaults from null appService.
+ if (appService != null) {
+ appService.indicateMenuVisibility(false, mSlotId);
+ } else {
+ CatLog.d(LOG_TAG, "onPause: null appService.");
+ }
cancelTimeOut();
}
@Override
+ public void onStop() {
+ super.onStop();
+ CatLog.d(LOG_TAG, "onStop, slot id: " + mSlotId + "," + mIsResponseSent + "," + mState);
+ //The menu should stay in background, if
+ //1. the dialog is pop up in the screen, but the user does not response to the dialog.
+ //2. the menu activity enters Stop state (e.g pressing HOME key) but mIsResponseSent is false.
+ if (mIsResponseSent) {
+ // ONLY finish SECONDARY menu. MAIN menu should always stay in the root of stack.
+ if (mState == STATE_SECONDARY) {
+ if (!appService.isStkDialogActivated(mContext)) {
+ CatLog.d(LOG_TAG, "STATE_SECONDARY finish.");
+ cancelTimeOut();//To avoid the timer time out and send TR again.
+ finish();
+ } else {
+ if (appService != null) {
+ appService.getStkContext(mSlotId).setPendingActivityInstance(this);
+ }
+ }
+ }
+ } else {
+ if (appService != null) {
+ appService.getStkContext(mSlotId).setPendingActivityInstance(this);
+ } else {
+ CatLog.d(LOG_TAG, "onStop: null appService.");
+ }
+ }
+ }
+
+ @Override
public void onDestroy() {
getListView().setOnCreateContextMenuListener(null);
super.onDestroy();
-
- CatLog.d(this, "onDestroy");
+ CatLog.d(LOG_TAG, "onDestroy" + "," + mState);
+ //isMenuPending: if input act is finish by stkappservice when OP_LAUNCH_APP again,
+ //we can not send TR here, since the input cmd is waiting user to process.
+ if (!mIsResponseSent && !appService.isMenuPending(mSlotId)) {
+ CatLog.d(LOG_TAG, "handleDestroy - Send End Session");
+ sendResponse(StkAppService.RES_ID_END_SESSION);
+ }
+ if (mState == STATE_MAIN) {
+ if (appService != null) {
+ appService.getStkContext(mSlotId).setMainActivityInstance(null);
+ } else {
+ CatLog.d(LOG_TAG, "onDestroy: null appService.");
+ }
+ }
}
@Override
@@ -224,6 +313,8 @@
mAcceptUsersInput = false;
// send session end response.
sendResponse(StkAppService.RES_ID_END_SESSION);
+ cancelTimeOut();
+ finish();
return true;
case StkApp.MENU_ID_HELP:
cancelTimeOut();
@@ -282,17 +373,22 @@
@Override
protected void onSaveInstanceState(Bundle outState) {
+ CatLog.d(LOG_TAG, "onSaveInstanceState: " + mSlotId);
outState.putInt("STATE", mState);
outState.putParcelable("MENU", mStkMenu);
+ outState.putBoolean("ACCEPT_USERS_INPUT", mAcceptUsersInput);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
+ CatLog.d(LOG_TAG, "onRestoreInstanceState: " + mSlotId);
mState = savedInstanceState.getInt("STATE");
mStkMenu = savedInstanceState.getParcelable("MENU");
+ mAcceptUsersInput = savedInstanceState.getBoolean("ACCEPT_USERS_INPUT");
}
private void cancelTimeOut() {
+ CatLog.d(LOG_TAG, "cancelTimeOut: " + mSlotId);
mTimeoutHandler.removeMessages(MSG_ID_TIMEOUT);
}
@@ -300,6 +396,7 @@
if (mState == STATE_SECONDARY) {
// Reset timeout.
cancelTimeOut();
+ CatLog.d(LOG_TAG, "startTimeOut: " + mSlotId);
mTimeoutHandler.sendMessageDelayed(mTimeoutHandler
.obtainMessage(MSG_ID_TIMEOUT), StkApp.UI_TIMEOUT);
}
@@ -338,7 +435,10 @@
if (intent != null) {
mState = intent.getIntExtra("STATE", STATE_MAIN);
+ mSlotId = intent.getIntExtra(StkAppService.SLOT_ID, -1);
+ CatLog.d(LOG_TAG, "slot id: " + mSlotId + ", state: " + mState);
} else {
+ CatLog.d(LOG_TAG, "finish!");
finish();
}
}
@@ -350,11 +450,11 @@
item = mStkMenu.items.get(position);
} catch (IndexOutOfBoundsException e) {
if (StkApp.DBG) {
- CatLog.d(this, "Invalid menu");
+ CatLog.d(LOG_TAG, "IOOBE Invalid menu");
}
} catch (NullPointerException e) {
if (StkApp.DBG) {
- CatLog.d(this, "Invalid menu");
+ CatLog.d(LOG_TAG, "NPE Invalid menu");
}
}
}
@@ -366,8 +466,12 @@
}
private void sendResponse(int resId, int itemId, boolean help) {
+ CatLog.d(LOG_TAG, "sendResponse resID[" + resId + "] itemId[" + itemId +
+ "] help[" + help + "]");
+ mIsResponseSent = true;
Bundle args = new Bundle();
args.putInt(StkAppService.OPCODE, StkAppService.OP_RESPONSE);
+ args.putInt(StkAppService.SLOT_ID, mSlotId);
args.putInt(StkAppService.RES_ID, resId);
args.putInt(StkAppService.MENU_SELECTION, itemId);
args.putBoolean(StkAppService.HELP, help);
diff --git a/src/com/android/stk/ToneDialog.java b/src/com/android/stk/ToneDialog.java
index b68340b..57a977d 100644
--- a/src/com/android/stk/ToneDialog.java
+++ b/src/com/android/stk/ToneDialog.java
@@ -27,7 +27,7 @@
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
-
+import com.android.internal.telephony.cat.CatLog;
import com.android.internal.telephony.cat.TextMessage;
import com.android.internal.telephony.cat.ToneSettings;
@@ -39,8 +39,11 @@
TextMessage toneMsg = null;
ToneSettings settings = null;
TonePlayer player = null;
+ int mSlotId = -1;
boolean mIsResponseSent = false;
+ private static final String LOG_TAG = new Object(){}.getClass().getEnclosingClass().getName();
+
/**
* Handler used to stop tones from playing when the duration ends.
*/
@@ -65,6 +68,7 @@
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ CatLog.d(LOG_TAG, "onCreate");
mVibrator = (Vibrator)getSystemService(VIBRATOR_SERVICE);
initFromIntent(getIntent());
@@ -79,7 +83,12 @@
ImageView iv = (ImageView) findViewById(R.id.icon);
// set text and icon
- tv.setText(toneMsg.text);
+ if ((null == toneMsg) || (null == toneMsg.text) || (toneMsg.text.equals(""))) {
+ CatLog.d(LOG_TAG, "onCreate - null tone text");
+ } else {
+ tv.setText(toneMsg.text);
+ }
+
if (toneMsg.icon == null) {
iv.setImageResource(com.android.internal.R.drawable.ic_volume);
} else {
@@ -87,6 +96,12 @@
}
// Start playing tone and vibration
+ if (null == settings) {
+ CatLog.d(LOG_TAG, "onCreate - null settings - finish");
+ finish();
+ return;
+ }
+
player = new TonePlayer();
player.play(settings.tone);
int timeout = StkApp.calculateDurationInMilis(settings.duration);
@@ -94,7 +109,7 @@
timeout = StkApp.TONE_DFEAULT_TIMEOUT;
}
mToneStopper.sendEmptyMessageDelayed(MSG_ID_STOP_TONE, timeout);
- if (settings.vibrate) {
+ if (settings.vibrate && mVibrator != null) {
mVibrator.vibrate(timeout);
}
}
@@ -102,12 +117,20 @@
@Override
protected void onDestroy() {
super.onDestroy();
- if (mIsResponseSent) {
- mToneStopper.removeMessages(MSG_ID_STOP_TONE);
+ CatLog.d(LOG_TAG, "onDestroy");
+
+ mToneStopper.removeMessages(MSG_ID_STOP_TONE);
+ if (!mIsResponseSent) {
+ sendResponse(StkAppService.RES_ID_END_SESSION);
}
- player.stop();
- player.release();
- mVibrator.cancel();
+
+ if (null != player) {
+ player.stop();
+ player.release();
+ }
+ if (null != mVibrator) {
+ mVibrator.cancel();
+ }
}
@Override
@@ -138,11 +161,13 @@
}
toneMsg = intent.getParcelableExtra("TEXT");
settings = intent.getParcelableExtra("TONE");
+ mSlotId = intent.getIntExtra(StkAppService.SLOT_ID, -1);
}
private void sendResponse(int resId) {
Bundle args = new Bundle();
args.putInt(StkAppService.OPCODE, StkAppService.OP_RESPONSE);
+ args.putInt(StkAppService.SLOT_ID, mSlotId);
args.putInt(StkAppService.RES_ID, resId);
startService(new Intent(this, StkAppService.class).putExtras(args));
mIsResponseSent = true;