Merge "Fix terminal response not sent during sim hotswap."
diff --git a/OWNERS b/OWNERS
index cb08ba3..46b828f 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1,6 @@
amitmahajan@google.com
rgreenwalt@google.com
-sanketpadawe@google.com
jminjie@google.com
+hallliu@google.com
+paulye@google.com
+breadley@google.com
diff --git a/src/com/android/stk/StkAppService.java b/src/com/android/stk/StkAppService.java
index 97fcd6c..055cbec 100644
--- a/src/com/android/stk/StkAppService.java
+++ b/src/com/android/stk/StkAppService.java
@@ -29,6 +29,7 @@
import android.app.ActivityManagerNative;
import android.app.IProcessObserver;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -90,8 +91,8 @@
import java.util.Iterator;
import java.util.LinkedList;
-import java.lang.System;
import java.util.List;
+import java.util.regex.Pattern;
import static com.android.internal.telephony.cat.CatCmdMessage.
SetupEventListConstants.IDLE_SCREEN_AVAILABLE_EVENT;
@@ -138,6 +139,8 @@
private CatCmdMessage mCurrentSetupEventCmd = null;
private CatCmdMessage mIdleModeTextCmd = null;
private boolean mIdleModeTextVisible = false;
+ // Determins whether the current session was initiated by user operation.
+ protected boolean mIsSessionFromUser = false;
final synchronized void setPendingActivityInstance(Activity act) {
CatLog.d(this, "setPendingActivityInstance act : " + mSlotId + ", " + act);
callSetActivityInstMsg(OP_SET_ACT_INST, mSlotId, act);
@@ -634,20 +637,44 @@
case OP_SET_ACT_INST:
Activity act = (Activity) msg.obj;
if (mStkContext[slotId].mActivityInstance != act) {
- CatLog.d(LOG_TAG, "Set activity instance - " + act);
+ CatLog.d(LOG_TAG, "Set pending activity instance - " + act);
Activity previous = mStkContext[slotId].mActivityInstance;
mStkContext[slotId].mActivityInstance = act;
- // Finish the previous one if it has not been finished yet somehow.
- if (previous != null && !previous.isDestroyed() && !previous.isFinishing()) {
+ // Finish the previous one if it was replaced with new one
+ // but it has not been finished yet somehow.
+ if (act != null && previous != null && !previous.isDestroyed()
+ && !previous.isFinishing()) {
CatLog.d(LOG_TAG, "Finish the previous pending activity - " + previous);
previous.finish();
}
+ // Pending activity is registered in the following 2 scnarios;
+ // A. TERMINAL RESPONSE was sent to the card.
+ // B. Activity was moved to the background before TR is sent to the card.
+ // No need to observe idle screen for the pending activity in the scenario A.
+ if (act != null && mStkContext[slotId].mCmdInProgress) {
+ startToObserveIdleScreen(slotId);
+ } else {
+ if (mStkContext[slotId].mCurrentCmd != null) {
+ unregisterProcessObserver(
+ mStkContext[slotId].mCurrentCmd.getCmdType(), slotId);
+ }
+ }
}
break;
case OP_SET_DAL_INST:
Activity dal = (Activity) msg.obj;
- CatLog.d(LOG_TAG, "Set dialog instance. " + dal);
- mStkContext[slotId].mDialogInstance = dal;
+ if (mStkContext[slotId].mDialogInstance != dal) {
+ CatLog.d(LOG_TAG, "Set pending dialog instance - " + dal);
+ mStkContext[slotId].mDialogInstance = dal;
+ if (dal != null) {
+ startToObserveIdleScreen(slotId);
+ } else {
+ if (mStkContext[slotId].mCurrentCmd != null) {
+ unregisterProcessObserver(
+ mStkContext[slotId].mCurrentCmd.getCmdType(), slotId);
+ }
+ }
+ }
break;
case OP_SET_IMMED_DAL_INST:
Activity immedDal = (Activity) msg.obj;
@@ -711,15 +738,6 @@
// Clear Idle Text
cancelIdleText(slotId);
}
-
- if (state.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET) {
- // Uninstall STkmenu
- if (isAllOtherCardsAbsent(slotId)) {
- StkAppInstaller.unInstall(mContext);
- }
- mStkContext[slotId].mCurrentMenu = null;
- mStkContext[slotId].mMainCmd = null;
- }
}
}
}
@@ -770,8 +788,36 @@
return false;
}
- private void handleIdleScreen(int slotId) {
+ private void startToObserveIdleScreen(int slotId) {
+ if (!mStkContext[slotId].mIsSessionFromUser) {
+ if (!isScreenIdle()) {
+ synchronized (this) {
+ if (mProcessObserver == null && !mServiceHandler.hasMessages(OP_IDLE_SCREEN)) {
+ registerProcessObserver();
+ }
+ }
+ } else {
+ handleIdleScreen(slotId);
+ }
+ }
+ }
+ private void handleIdleScreen(int slotId) {
+ // It might be hard for user to recognize that the dialog or screens belong to SIM Toolkit
+ // application if the current session was not initiated by user but by the SIM card,
+ // so it is recommended to send TERMINAL RESPONSE if user goes to the idle screen.
+ if (!mStkContext[slotId].mIsSessionFromUser) {
+ Activity dialog = mStkContext[slotId].getPendingDialogInstance();
+ if (dialog != null) {
+ dialog.finish();
+ mStkContext[slotId].mDialogInstance = null;
+ }
+ Activity activity = mStkContext[slotId].getPendingActivityInstance();
+ if (activity != null) {
+ activity.finish();
+ mStkContext[slotId].mActivityInstance = null;
+ }
+ }
// If the idle screen event is present in the list need to send the
// response to SIM.
CatLog.d(this, "Need to send IDLE SCREEN Available event to SIM");
@@ -798,6 +844,20 @@
}
}
+ /**
+ * Sends TERMINAL RESPONSE or ENVELOPE
+ *
+ * @param args detailed parameters of the response
+ * @param slotId slot identifier
+ */
+ public void sendResponse(Bundle args, int slotId) {
+ Message msg = mServiceHandler.obtainMessage();
+ msg.arg1 = OP_RESPONSE;
+ msg.arg2 = slotId;
+ msg.obj = args;
+ mServiceHandler.sendMessage(msg);
+ }
+
private void sendResponse(int resId, int slotId, boolean confirm) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = OP_RESPONSE;
@@ -883,6 +943,7 @@
CatLog.d(LOG_TAG, "[handleSessionEnd][mMainCmd is null!]");
}
mStkContext[slotId].lastSelectedItem = null;
+ mStkContext[slotId].mIsSessionFromUser = false;
// In case of SET UP MENU command which removed the app, don't
// update the current menu member.
if (mStkContext[slotId].mCurrentMenu != null && mStkContext[slotId].mMainCmd != null) {
@@ -1153,6 +1214,7 @@
}
}
+ @SuppressWarnings("FallThrough")
private void handleCmdResponse(Bundle args, int slotId) {
CatLog.d(LOG_TAG, "handleCmdResponse, sim id: " + slotId);
if (mStkContext[slotId].mCurrentCmd == null) {
@@ -1182,6 +1244,8 @@
int menuSelection = args.getInt(MENU_SELECTION);
switch(mStkContext[slotId].mCurrentMenuCmd.getCmdType()) {
case SET_UP_MENU:
+ mStkContext[slotId].mIsSessionFromUser = true;
+ // Fall through
case SELECT_ITEM:
mStkContext[slotId].lastSelectedItem = getItemName(menuSelection, slotId);
if (helpRequired) {
@@ -1624,19 +1688,23 @@
return getNotificationId(slotId) + (notificationType * mSimCount);
}
- 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;
+ /**
+ * Checks whether the dialog exists as the top activity of this task.
+ *
+ * @return true if the top activity of this task is the dialog.
+ */
+ public boolean isStkDialogActivated() {
+ ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ ComponentName componentName = am.getAppTasks().get(0).getTaskInfo().topActivity;
+ if (componentName != null) {
+ String[] split = componentName.getClassName().split(Pattern.quote("."));
+ String topActivity = split[split.length - 1];
+ CatLog.d(LOG_TAG, "Top activity: " + topActivity);
+ if (TextUtils.equals(topActivity, StkDialogActivity.class.getSimpleName())) {
+ return true;
+ }
}
- CatLog.d(LOG_TAG, "activated : " + activated);
- return activated;
+ return false;
}
private void replaceEventList(int slotId) {
@@ -1766,6 +1834,7 @@
}
};
ActivityManagerNative.getDefault().registerProcessObserver(observer);
+ CatLog.d(this, "Started to observe the foreground activity");
mProcessObserver = observer;
} catch (RemoteException e) {
CatLog.d(this, "Failed to register the process observer");
@@ -1803,6 +1872,7 @@
if (mProcessObserver != null) {
try {
ActivityManagerNative.getDefault().unregisterProcessObserver(mProcessObserver);
+ CatLog.d(this, "Stopped to observe the foreground activity");
mProcessObserver = null;
} catch (RemoteException e) {
CatLog.d(this, "Failed to unregister the process observer");
diff --git a/src/com/android/stk/StkDialogActivity.java b/src/com/android/stk/StkDialogActivity.java
index 3503134..1462480 100644
--- a/src/com/android/stk/StkDialogActivity.java
+++ b/src/com/android/stk/StkDialogActivity.java
@@ -48,6 +48,8 @@
private StkAppService appService = StkAppService.getInstance();
// Determines whether Terminal Response (TR) has been sent
private boolean mIsResponseSent = false;
+ // Determines whether this is in the pending state.
+ private boolean mIsPending = false;
// Utilize AlarmManager for real-time countdown
private static final String DIALOG_ALARM_TAG = LOG_TAG;
private static final long NO_DIALOG_ALARM = -1;
@@ -58,6 +60,8 @@
private static final String ALARM_TIME_KEY = "alarm_time";
private static final String RESPONSE_SENT_KEY = "response_sent";
private static final String SLOT_ID_KEY = "slotid";
+ private static final String PENDING = "pending";
+
private AlertDialog mAlertDialog;
@@ -85,9 +89,7 @@
@Override
public void onClick(DialogInterface dialog, int id) {
CatLog.d(LOG_TAG, "OK Clicked!, mSlotId: " + mSlotId);
- cancelTimeOut();
sendResponse(StkAppService.RES_ID_CONFIRM, true);
- finish();
}
});
@@ -96,9 +98,7 @@
@Override
public void onClick(DialogInterface dialog,int id) {
CatLog.d(LOG_TAG, "Cancel Clicked!, mSlotId: " + mSlotId);
- cancelTimeOut();
sendResponse(StkAppService.RES_ID_CONFIRM, false);
- finish();
}
});
@@ -106,9 +106,7 @@
@Override
public void onCancel(DialogInterface dialog) {
CatLog.d(LOG_TAG, "Moving backward!, mSlotId: " + mSlotId);
- cancelTimeOut();
sendResponse(StkAppService.RES_ID_BACKWARD);
- finish();
}
});
@@ -160,6 +158,8 @@
super.onResume();
CatLog.d(LOG_TAG, "onResume - mIsResponseSent[" + mIsResponseSent +
"], sim id: " + mSlotId);
+ // The pending dialog is unregistered if this instance was registered as it before.
+ setPendingState(false);
/*
* If the userClear flag is set and dialogduration is set to 0, the display Text
@@ -216,23 +216,13 @@
CatLog.d(LOG_TAG, "onStop - before Send CONFIRM false mIsResponseSent[" +
mIsResponseSent + "], sim id: " + mSlotId);
- // Avoid calling finish() or setPendingDialogInstance()
- // if the activity is being restarted now.
- if (isChangingConfigurations()) {
+ // Nothing should be done here if this activity is being finished or restarted now.
+ if (isFinishing() || isChangingConfigurations()) {
return;
}
- if (!mTextMsg.responseNeeded) {
- return;
- }
- if (!mIsResponseSent) {
- appService.getStkContext(mSlotId).setPendingDialogInstance(this);
- } else {
- CatLog.d(LOG_TAG, "finish.");
- appService.getStkContext(mSlotId).setPendingDialogInstance(null);
- cancelTimeOut();
- finish();
- }
+ // This is registered as the pending dialog as this was sent to the background.
+ setPendingState(true);
}
@Override
@@ -270,6 +260,7 @@
outState.putBoolean(RESPONSE_SENT_KEY, mIsResponseSent);
outState.putLong(ALARM_TIME_KEY, mAlarmTime);
outState.putInt(SLOT_ID_KEY, mSlotId);
+ outState.putBoolean(PENDING, mIsPending);
}
@Override
@@ -282,7 +273,11 @@
mIsResponseSent = savedInstanceState.getBoolean(RESPONSE_SENT_KEY);
mAlarmTime = savedInstanceState.getLong(ALARM_TIME_KEY, NO_DIALOG_ALARM);
mSlotId = savedInstanceState.getInt(SLOT_ID_KEY);
- appService.getStkContext(mSlotId).setPendingDialogInstance(this);
+
+ // The pending dialog must be replaced if the previous instance was in the pending state.
+ if (savedInstanceState.getBoolean(PENDING)) {
+ setPendingState(true);
+ }
if (mAlarmTime != NO_DIALOG_ALARM) {
startTimeOut();
@@ -308,7 +303,18 @@
}
}
+ private void setPendingState(boolean on) {
+ if (mTextMsg.responseNeeded) {
+ if (mIsPending != on) {
+ appService.getStkContext(mSlotId).setPendingDialogInstance(on ? this : null);
+ mIsPending = on;
+ }
+ }
+ }
+
private void sendResponse(int resId, boolean confirmed) {
+ cancelTimeOut();
+
if (mSlotId == -1) {
CatLog.d(LOG_TAG, "sim id is invalid");
return;
@@ -330,6 +336,10 @@
startService(new Intent(this, StkAppService.class).putExtras(args));
mIsResponseSent = true;
}
+ if (!isFinishing()) {
+ finish();
+ }
+
}
private void sendResponse(int resId) {
@@ -391,7 +401,6 @@
CatLog.d(LOG_TAG, "The alarm time is reached");
mAlarmTime = NO_DIALOG_ALARM;
sendResponse(StkAppService.RES_ID_TIMEOUT);
- finish();
}
};
}
diff --git a/src/com/android/stk/StkInputActivity.java b/src/com/android/stk/StkInputActivity.java
index fa688c7..26ae4ce 100644
--- a/src/com/android/stk/StkInputActivity.java
+++ b/src/com/android/stk/StkInputActivity.java
@@ -33,6 +33,7 @@
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
+import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
@@ -80,6 +81,7 @@
private static final String RESPONSE_SENT_KEY = "response_sent";
private static final String INPUT_STRING_KEY = "input_string";
private static final String ALARM_TIME_KEY = "alarm_time";
+ private static final String PENDING = "pending";
private static final String INPUT_ALARM_TAG = LOG_TAG;
private static final long NO_INPUT_ALARM = -1;
@@ -88,6 +90,8 @@
private StkAppService appService = StkAppService.getInstance();
private boolean mIsResponseSent = false;
+ // Determines whether this is in the pending state.
+ private boolean mIsPending = false;
private int mSlotId = -1;
// Click listener to handle buttons press..
@@ -108,8 +112,8 @@
input = mTextIn.getText().toString();
break;
case R.id.button_cancel:
- appService.getStkContext(mSlotId).setPendingActivityInstance(this);
sendResponse(StkAppService.RES_ID_END_SESSION);
+ finish();
return;
// Yes/No layout buttons.
case R.id.button_yes:
@@ -142,7 +146,6 @@
break;
}
CatLog.d(LOG_TAG, "handleClick, ready to response");
- appService.getStkContext(mSlotId).setPendingActivityInstance(this);
sendResponse(StkAppService.RES_ID_INPUT, input, false);
}
@@ -208,6 +211,11 @@
super.onResume();
CatLog.d(LOG_TAG, "onResume - mIsResponseSent[" + mIsResponseSent +
"], slot id: " + mSlotId);
+ // If the terminal has already sent response to the card when this activity is resumed,
+ // keep this as a pending activity as this should be finished when the session ends.
+ if (!mIsResponseSent) {
+ setPendingState(false);
+ }
if (mAlarmTime == NO_INPUT_ALARM) {
startTimeOut();
@@ -228,17 +236,21 @@
super.onStop();
CatLog.d(LOG_TAG, "onStop - mIsResponseSent[" + mIsResponseSent + "]");
- // Nothing should be done here if this activity is being restarted now.
- if (isChangingConfigurations()) {
+ // Nothing should be done here if this activity is being finished or restarted now.
+ if (isFinishing() || isChangingConfigurations()) {
return;
}
- // It is unnecessary to keep this activity if the response was already sent and
- // this got invisible because of the other full-screen activity in this application.
- if (mIsResponseSent && appService.isTopOfStack()) {
- finish();
+ if (mIsResponseSent) {
+ // It is unnecessary to keep this activity if the response was already sent and
+ // the dialog activity is NOT on the top of this activity.
+ if (!appService.isStkDialogActivated()) {
+ finish();
+ }
} else {
- appService.getStkContext(mSlotId).setPendingActivityInstance(this);
+ // This should be registered as the pending activity here
+ // only when no response has been sent back to the card.
+ setPendingState(true);
}
}
@@ -282,7 +294,6 @@
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
CatLog.d(LOG_TAG, "onKeyDown - KEYCODE_BACK");
- appService.getStkContext(mSlotId).setPendingActivityInstance(this);
sendResponse(StkAppService.RES_ID_BACKWARD, null, false);
return true;
}
@@ -314,14 +325,17 @@
+ 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);
}
args.putBoolean(StkAppService.HELP, help);
- startService(new Intent(this, StkAppService.class).putExtras(args));
+ appService.sendResponse(args, mSlotId);
+
+ // This instance should be set as a pending activity and finished by the service
+ if (resId != StkAppService.RES_ID_END_SESSION) {
+ setPendingState(true);
+ }
}
@Override
@@ -368,7 +382,6 @@
return true;
case StkApp.MENU_ID_HELP:
sendResponse(StkAppService.RES_ID_INPUT, "", true);
- finish();
return true;
}
return false;
@@ -380,6 +393,7 @@
outState.putBoolean(RESPONSE_SENT_KEY, mIsResponseSent);
outState.putString(INPUT_STRING_KEY, mTextIn.getText().toString());
outState.putLong(ALARM_TIME_KEY, mAlarmTime);
+ outState.putBoolean(PENDING, mIsPending);
}
@Override
@@ -400,6 +414,22 @@
if (mAlarmTime != NO_INPUT_ALARM) {
startTimeOut();
}
+
+ if (!mIsResponseSent && !savedInstanceState.getBoolean(PENDING)) {
+ // If this is in the foreground and no response has been sent to the card,
+ // this must not be registered as pending activity by the previous instance.
+ // No need to renew nor clear pending activity in this case.
+ } else {
+ // Renew the instance of the pending activity.
+ setPendingState(true);
+ }
+ }
+
+ private void setPendingState(boolean on) {
+ if (mIsPending != on) {
+ appService.getStkContext(mSlotId).setPendingActivityInstance(on ? this : null);
+ mIsPending = on;
+ }
}
public void beforeTextChanged(CharSequence s, int start, int count,
@@ -501,6 +531,10 @@
.getInstance());
}
mTextIn.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN);
+ // Request the initial focus on the edit box and show the software keyboard.
+ mTextIn.requestFocus();
+ getWindow().setSoftInputMode(
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
// Set default text if present.
if (mStkInput.defaultText != null) {
mTextIn.setText(mStkInput.defaultText);
@@ -544,8 +578,6 @@
public void onAlarm() {
CatLog.d(LOG_TAG, "The alarm time is reached");
mAlarmTime = NO_INPUT_ALARM;
- appService.getStkContext(mSlotId).setPendingActivityInstance(
- StkInputActivity.this);
sendResponse(StkAppService.RES_ID_TIMEOUT);
}
};
diff --git a/src/com/android/stk/StkMenuActivity.java b/src/com/android/stk/StkMenuActivity.java
index 87884db..bc62e5e 100644
--- a/src/com/android/stk/StkMenuActivity.java
+++ b/src/com/android/stk/StkMenuActivity.java
@@ -54,6 +54,8 @@
private boolean mAcceptUsersInput = true;
private int mSlotId = -1;
private boolean mIsResponseSent = false;
+ // Determines whether this is in the pending state.
+ private boolean mIsPending = false;
private TextView mTitleTextView = null;
private ImageView mTitleIconView = null;
@@ -69,6 +71,7 @@
private static final String ACCEPT_USERS_INPUT_KEY = "accept_users_input";
private static final String RESPONSE_SENT_KEY = "response_sent";
private static final String ALARM_TIME_KEY = "alarm_time";
+ private static final String PENDING = "pending";
private static final String SELECT_ALARM_TAG = LOG_TAG;
private static final long NO_SELECT_ALARM = -1;
@@ -131,10 +134,6 @@
}
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);
invalidateOptionsMenu();
}
@@ -152,7 +151,6 @@
switch (mState) {
case STATE_SECONDARY:
CatLog.d(LOG_TAG, "STATE_SECONDARY");
- appService.getStkContext(mSlotId).setPendingActivityInstance(this);
sendResponse(StkAppService.RES_ID_BACKWARD);
return true;
case STATE_MAIN:
@@ -166,12 +164,6 @@
}
@Override
- public void onRestart() {
- super.onRestart();
- CatLog.d(LOG_TAG, "onRestart, slot id: " + mSlotId);
- }
-
- @Override
public void onResume() {
super.onResume();
@@ -190,6 +182,11 @@
}
displayMenu();
+ // If the terminal has already sent response to the card when this activity is resumed,
+ // keep this as a pending activity as this should be finished when the session ends.
+ if (!mIsResponseSent) {
+ setPendingState(false);
+ }
if (mAlarmTime == NO_SELECT_ALARM) {
startTimeOut();
}
@@ -225,35 +222,21 @@
super.onStop();
CatLog.d(LOG_TAG, "onStop, slot id: " + mSlotId + "," + mIsResponseSent + "," + mState);
- // Nothing should be done here if this activity is being restarted now.
- if (isChangingConfigurations()) {
+ // Nothing should be done here if this activity is being finished or restarted now.
+ if (isFinishing() || isChangingConfigurations()) {
return;
}
- //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(this)) {
- 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);
- }
- }
+ // It is unnecessary to keep this activity if the response was already sent and
+ // the dialog activity is NOT on the top of this activity.
+ if (mState == STATE_SECONDARY && !appService.isStkDialogActivated()) {
+ finish();
}
} else {
- if (appService != null) {
- if (mState == STATE_SECONDARY) {
- appService.getStkContext(mSlotId).setPendingActivityInstance(this);
- }
- } else {
- CatLog.d(LOG_TAG, "onStop: null appService.");
- }
+ // This instance should be registered as the pending activity here
+ // only when no response has been sent back to the card.
+ setPendingState(true);
}
}
@@ -363,6 +346,7 @@
outState.putBoolean(ACCEPT_USERS_INPUT_KEY, mAcceptUsersInput);
outState.putBoolean(RESPONSE_SENT_KEY, mIsResponseSent);
outState.putLong(ALARM_TIME_KEY, mAlarmTime);
+ outState.putBoolean(PENDING, mIsPending);
}
@Override
@@ -385,6 +369,24 @@
if (mAlarmTime != NO_SELECT_ALARM) {
startTimeOut();
}
+
+ if (!mIsResponseSent && !savedInstanceState.getBoolean(PENDING)) {
+ // If this is in the foreground and no response has been sent to the card,
+ // this must not be registered as pending activity by the previous instance.
+ // No need to renew nor clear pending activity in this case.
+ } else {
+ // Renew the instance of the pending activity.
+ setPendingState(true);
+ }
+ }
+
+ private void setPendingState(boolean on) {
+ if (mState == STATE_SECONDARY) {
+ if (mIsPending != on) {
+ appService.getStkContext(mSlotId).setPendingActivityInstance(on ? this : null);
+ mIsPending = on;
+ }
+ }
}
private void cancelTimeOut() {
@@ -498,12 +500,15 @@
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);
- startService(new Intent(this, StkAppService.class).putExtras(args));
+ appService.sendResponse(args, mSlotId);
+
+ // This instance should be set as a pending activity and finished by the service.
+ if (resId != StkAppService.RES_ID_END_SESSION) {
+ setPendingState(true);
+ }
}
private final BroadcastReceiver mLocalBroadcastReceiver = new BroadcastReceiver() {
@@ -525,8 +530,6 @@
public void onAlarm() {
CatLog.d(LOG_TAG, "The alarm time is reached");
mAlarmTime = NO_SELECT_ALARM;
- appService.getStkContext(mSlotId).setPendingActivityInstance(
- StkMenuActivity.this);
sendResponse(StkAppService.RES_ID_TIMEOUT);
}
};