blob: 4fb5f91d30af8c7aeb9e6690418f101441177123 [file] [log] [blame]
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.stk;
18
Preeti Ahuja95919342013-10-01 18:18:55 -070019import android.app.ActivityManager;
20import android.app.ActivityManager.RunningTaskInfo;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -050021import android.app.AlertDialog;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080022import android.app.Notification;
23import android.app.NotificationManager;
24import android.app.PendingIntent;
25import android.app.Service;
Wink Savillee68857d2014-10-17 15:23:05 -070026import android.app.Activity;
27import android.app.ActivityManager;
28import android.app.ActivityManager.RecentTaskInfo;
29import android.app.ActivityManager.RunningAppProcessInfo;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080030import android.content.Context;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -050031import android.content.DialogInterface;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080032import android.content.Intent;
Preeti Ahuja95919342013-10-01 18:18:55 -070033import android.content.res.Configuration;
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +010034import android.graphics.Bitmap;
35import android.graphics.BitmapFactory;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080036import android.net.Uri;
37import android.os.Bundle;
38import android.os.Handler;
39import android.os.IBinder;
40import android.os.Looper;
41import android.os.Message;
Preeti Ahuja95919342013-10-01 18:18:55 -070042import android.provider.Settings;
Wink Saville56469d52009-04-02 01:37:03 -070043import android.telephony.TelephonyManager;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080044import android.view.Gravity;
45import android.view.LayoutInflater;
46import android.view.View;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -050047import android.view.Window;
48import android.view.WindowManager;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080049import android.widget.ImageView;
50import android.widget.RemoteViews;
51import android.widget.TextView;
52import android.widget.Toast;
Wink Savillee68857d2014-10-17 15:23:05 -070053import android.content.BroadcastReceiver;
54import android.content.IntentFilter;
55import android.content.pm.ApplicationInfo;
56import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080057
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070058import com.android.internal.telephony.cat.AppInterface;
Preeti Ahuja95919342013-10-01 18:18:55 -070059import com.android.internal.telephony.cat.LaunchBrowserMode;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070060import com.android.internal.telephony.cat.Menu;
61import com.android.internal.telephony.cat.Item;
Pierre Fröjd97503262010-11-08 13:59:36 +010062import com.android.internal.telephony.cat.Input;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070063import com.android.internal.telephony.cat.ResultCode;
64import com.android.internal.telephony.cat.CatCmdMessage;
65import com.android.internal.telephony.cat.CatCmdMessage.BrowserSettings;
Preeti Ahuja95919342013-10-01 18:18:55 -070066import com.android.internal.telephony.cat.CatCmdMessage.SetupEventListSettings;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070067import com.android.internal.telephony.cat.CatLog;
68import com.android.internal.telephony.cat.CatResponseMessage;
69import com.android.internal.telephony.cat.TextMessage;
Wink Saville94e982b2014-07-11 07:38:14 -070070import com.android.internal.telephony.uicc.IccRefreshResponse;
71import com.android.internal.telephony.uicc.IccCardStatus.CardState;
Wink Savillee68857d2014-10-17 15:23:05 -070072import com.android.internal.telephony.PhoneConstants;
73import com.android.internal.telephony.TelephonyIntents;
74import com.android.internal.telephony.IccCardConstants;
75import com.android.internal.telephony.uicc.UiccController;
Preeti Ahuja95919342013-10-01 18:18:55 -070076import com.android.internal.telephony.GsmAlphabet;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080077
78import java.util.LinkedList;
Wink Savillee68857d2014-10-17 15:23:05 -070079import java.lang.System;
80import java.util.List;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080081
Preeti Ahuja95919342013-10-01 18:18:55 -070082import static com.android.internal.telephony.cat.CatCmdMessage.
83 SetupEventListConstants.IDLE_SCREEN_AVAILABLE_EVENT;
84import static com.android.internal.telephony.cat.CatCmdMessage.
85 SetupEventListConstants.LANGUAGE_SELECTION_EVENT;
86
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080087/**
88 * SIM toolkit application level service. Interacts with Telephopny messages,
89 * application's launch and user input from STK UI elements.
Wink Saville79085fc2009-06-09 10:27:23 -070090 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080091 */
92public class StkAppService extends Service implements Runnable {
93
94 // members
Wink Savillee68857d2014-10-17 15:23:05 -070095 protected class StkContext {
96 protected CatCmdMessage mMainCmd = null;
97 protected CatCmdMessage mCurrentCmd = null;
98 protected CatCmdMessage mCurrentMenuCmd = null;
99 protected Menu mCurrentMenu = null;
100 protected String lastSelectedItem = null;
101 protected boolean mMenuIsVisible = false;
102 protected boolean mIsInputPending = false;
103 protected boolean mIsMenuPending = false;
104 protected boolean mIsDialogPending = false;
105 protected boolean responseNeeded = true;
106 protected boolean launchBrowser = false;
107 protected BrowserSettings mBrowserSettings = null;
108 protected LinkedList<DelayedCmd> mCmdsQ = null;
109 protected boolean mCmdInProgress = false;
110 protected int mStkServiceState = STATE_UNKNOWN;
111 protected int mSetupMenuState = STATE_UNKNOWN;
112 protected int mMenuState = StkMenuActivity.STATE_INIT;
113 protected int mOpCode = -1;
114 private Activity mActivityInstance = null;
115 private Activity mDialogInstance = null;
116 private Activity mMainActivityInstance = null;
117 private boolean mBackGroundTRSent = false;
118 private int mSlotId = 0;
Preeti Ahuja95919342013-10-01 18:18:55 -0700119 private CatCmdMessage mIdleModeTextCmd = null;
Preeti Ahuja414bc412013-06-25 19:31:49 -0700120 private boolean mIsDisplayTextPending = false;
Preeti Ahuja95919342013-10-01 18:18:55 -0700121 private boolean mScreenIdle = true;
122 private SetupEventListSettings mSetupEventListSettings = null;
123 private boolean mClearSelectItem = false;
124 private boolean mDisplayTextDlgIsVisibile = false;
125 private CatCmdMessage mCurrentSetupEventCmd = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700126 final synchronized void setPendingActivityInstance(Activity act) {
127 CatLog.d(this, "setPendingActivityInstance act : " + mSlotId + ", " + act);
128 callSetActivityInstMsg(OP_SET_ACT_INST, mSlotId, act);
129 }
130 final synchronized Activity getPendingActivityInstance() {
131 CatLog.d(this, "getPendingActivityInstance act : " + mSlotId + ", " +
132 mActivityInstance);
133 return mActivityInstance;
134 }
135 final synchronized void setPendingDialogInstance(Activity act) {
136 CatLog.d(this, "setPendingDialogInstance act : " + mSlotId + ", " + act);
137 callSetActivityInstMsg(OP_SET_DAL_INST, mSlotId, act);
138 }
139 final synchronized Activity getPendingDialogInstance() {
140 CatLog.d(this, "getPendingDialogInstance act : " + mSlotId + ", " +
141 mDialogInstance);
142 return mDialogInstance;
143 }
144 final synchronized void setMainActivityInstance(Activity act) {
145 CatLog.d(this, "setMainActivityInstance act : " + mSlotId + ", " + act);
146 callSetActivityInstMsg(OP_SET_MAINACT_INST, mSlotId, act);
147 }
148 final synchronized Activity getMainActivityInstance() {
149 CatLog.d(this, "getMainActivityInstance act : " + mSlotId + ", " +
150 mMainActivityInstance);
151 return mMainActivityInstance;
152 }
153 }
154
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800155 private volatile Looper mServiceLooper;
156 private volatile ServiceHandler mServiceHandler;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800157 private Context mContext = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800158 private NotificationManager mNotificationManager = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800159 static StkAppService sInstance = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700160 private AppInterface[] mStkService = null;
161 private StkContext[] mStkContext = null;
162 private int mSimCount = 0;
Preeti Ahuja95919342013-10-01 18:18:55 -0700163
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800164 // Used for setting FLAG_ACTIVITY_NO_USER_ACTION when
165 // creating an intent.
166 private enum InitiatedByUserAction {
167 yes, // The action was started via a user initiated action
168 unknown, // Not known for sure if user initated the action
169 }
170
171 // constants
172 static final String OPCODE = "op";
173 static final String CMD_MSG = "cmd message";
174 static final String RES_ID = "response id";
175 static final String MENU_SELECTION = "menu selection";
176 static final String INPUT = "input";
177 static final String HELP = "help";
178 static final String CONFIRMATION = "confirm";
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500179 static final String CHOICE = "choice";
Wink Savillee68857d2014-10-17 15:23:05 -0700180 static final String SLOT_ID = "SLOT_ID";
181 static final String STK_CMD = "STK CMD";
182 static final String STK_DIALOG_URI = "stk://com.android.stk/dialog/";
183 static final String STK_MENU_URI = "stk://com.android.stk/menu/";
184 static final String STK_INPUT_URI = "stk://com.android.stk/input/";
185 static final String STK_TONE_URI = "stk://com.android.stk/tone/";
Preeti Ahuja95919342013-10-01 18:18:55 -0700186 static final String SCREEN_STATUS = "screen status";
187 static final String SCREEN_STATUS_REQUEST = "SCREEN_STATUS_REQUEST";
188
189 // These below constants are used for SETUP_EVENT_LIST
190 static final String SETUP_EVENT_TYPE = "event";
191 static final String SETUP_EVENT_CAUSE = "cause";
192
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800193 // operations ids for different service functionality.
194 static final int OP_CMD = 1;
195 static final int OP_RESPONSE = 2;
196 static final int OP_LAUNCH_APP = 3;
197 static final int OP_END_SESSION = 4;
198 static final int OP_BOOT_COMPLETED = 5;
199 private static final int OP_DELAYED_MSG = 6;
Wink Saville94e982b2014-07-11 07:38:14 -0700200 static final int OP_CARD_STATUS_CHANGED = 7;
Wink Savillee68857d2014-10-17 15:23:05 -0700201 static final int OP_SET_ACT_INST = 8;
202 static final int OP_SET_DAL_INST = 9;
203 static final int OP_SET_MAINACT_INST = 10;
Preeti Ahuja95919342013-10-01 18:18:55 -0700204 static final int OP_IDLE_SCREEN = 11;
205 static final int OP_LOCALE_CHANGED = 12;
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +0530206 static final int OP_ALPHA_NOTIFY = 13;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800207
Preeti Ahuja95919342013-10-01 18:18:55 -0700208 //Invalid SetupEvent
209 static final int INVALID_SETUP_EVENT = 0xFF;
210
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800211 // Response ids
212 static final int RES_ID_MENU_SELECTION = 11;
213 static final int RES_ID_INPUT = 12;
214 static final int RES_ID_CONFIRM = 13;
215 static final int RES_ID_DONE = 14;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500216 static final int RES_ID_CHOICE = 15;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800217
218 static final int RES_ID_TIMEOUT = 20;
219 static final int RES_ID_BACKWARD = 21;
220 static final int RES_ID_END_SESSION = 22;
221 static final int RES_ID_EXIT = 23;
222
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500223 static final int YES = 1;
224 static final int NO = 0;
225
Wink Savillee68857d2014-10-17 15:23:05 -0700226 static final int STATE_UNKNOWN = -1;
227 static final int STATE_NOT_EXIST = 0;
228 static final int STATE_EXIST = 1;
Wink Saville79085fc2009-06-09 10:27:23 -0700229
Wink Savillee68857d2014-10-17 15:23:05 -0700230 private static final String PACKAGE_NAME = "com.android.stk";
231 private static final String STK_MENU_ACTIVITY_NAME = PACKAGE_NAME + ".StkMenuActivity";
232 private static final String STK_INPUT_ACTIVITY_NAME = PACKAGE_NAME + ".StkInputActivity";
233 private static final String STK_DIALOG_ACTIVITY_NAME = PACKAGE_NAME + ".StkDialogActivity";
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800234 // Notification id used to display Idle Mode text in NotificationManager.
235 private static final int STK_NOTIFICATION_ID = 333;
Wink Savillee68857d2014-10-17 15:23:05 -0700236 private static final String LOG_TAG = new Object(){}.getClass().getEnclosingClass().getName();
Wink Saville79085fc2009-06-09 10:27:23 -0700237
238 // Inner class used for queuing telephony messages (proactive commands,
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800239 // session end) while the service is busy processing a previous message.
240 private class DelayedCmd {
241 // members
242 int id;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700243 CatCmdMessage msg;
Wink Savillee68857d2014-10-17 15:23:05 -0700244 int slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800245
Wink Savillee68857d2014-10-17 15:23:05 -0700246 DelayedCmd(int id, CatCmdMessage msg, int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800247 this.id = id;
248 this.msg = msg;
Wink Savillee68857d2014-10-17 15:23:05 -0700249 this.slotId = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800250 }
251 }
252
253 @Override
254 public void onCreate() {
Wink Savillee68857d2014-10-17 15:23:05 -0700255 CatLog.d(LOG_TAG, "onCreate()+");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800256 // Initialize members
Wink Savillee68857d2014-10-17 15:23:05 -0700257 int i = 0;
258 mContext = getBaseContext();
259 mSimCount = TelephonyManager.from(mContext).getSimCount();
260 CatLog.d(LOG_TAG, "simCount: " + mSimCount);
261 mStkService = new AppInterface[mSimCount];
262 mStkContext = new StkContext[mSimCount];
263 for (i = 0; i < mSimCount; i++) {
264 CatLog.d(LOG_TAG, "slotId: " + i);
265 if (null != UiccController.getInstance() && null != UiccController.getInstance()
266 .getUiccCard(i)) {
267 mStkService[i] = UiccController.getInstance().getUiccCard(i).getCatService();
268 } else {
269 CatLog.d(LOG_TAG, "Null instance: [" + UiccController.getInstance() + "],[" +
270 UiccController.getInstance().getUiccCard(i) + "]");
271 }
272 mStkContext[i] = new StkContext();
273 mStkContext[i].mSlotId = i;
274 mStkContext[i].mCmdsQ = new LinkedList<DelayedCmd>();
275 }
276
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800277 Thread serviceThread = new Thread(null, this, "Stk App Service");
278 serviceThread.start();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800279 mNotificationManager = (NotificationManager) mContext
280 .getSystemService(Context.NOTIFICATION_SERVICE);
281 sInstance = this;
282 }
283
284 @Override
285 public void onStart(Intent intent, int startId) {
Wink Savillee68857d2014-10-17 15:23:05 -0700286 if (intent == null) {
287 CatLog.d(LOG_TAG, "StkAppService onStart intent is null so return");
Banavathu, Srinivas Naik87cda962012-07-17 15:32:44 +0530288 return;
289 }
290
Wink Savillee68857d2014-10-17 15:23:05 -0700291 Bundle args = intent.getExtras();
292 if (args == null) {
293 CatLog.d(LOG_TAG, "StkAppService onStart args is null so return");
294 return;
295 }
296
297 int op = args.getInt(OPCODE);
298 int slotId = 0;
299 int i = 0;
300 if (op != OP_BOOT_COMPLETED) {
301 slotId = args.getInt(SLOT_ID);
302 }
303 CatLog.d(LOG_TAG, "onStart sim id: " + slotId + ", op: " + op + ", " + args);
304 if ((slotId >= 0 && slotId < mSimCount) && mStkService[slotId] == null) {
305 if (null != UiccController.getInstance() && null != UiccController.getInstance()
306 .getUiccCard(slotId)) {
307 mStkService[slotId] = UiccController.getInstance().getUiccCard(slotId)
308 .getCatService();
309 } else {
310 CatLog.d(LOG_TAG, "Null instance: [" + UiccController.getInstance() + "],[" +
311 UiccController.getInstance().getUiccCard(slotId)+"]");
312 }
313 if (mStkService[slotId] == null) {
314 CatLog.d(LOG_TAG, "mStkService is: " + mStkContext[slotId].mStkServiceState);
315 mStkContext[slotId].mStkServiceState = STATE_NOT_EXIST;
316 //Check other StkService state.
317 //If all StkServices are not available, stop itself and uninstall apk.
318 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
319 if (i != slotId
320 && (mStkContext[i].mStkServiceState == STATE_UNKNOWN
321 || mStkContext[i].mStkServiceState == STATE_EXIST)) {
322 break;
323 }
324 }
325 } else {
326 mStkContext[slotId].mStkServiceState = STATE_EXIST;
327 }
328 if (i == mSimCount) {
329 stopSelf();
330 StkAppInstaller.unInstall(mContext);
331 return;
332 }
333 }
334
Banavathu, Srinivas Naik87cda962012-07-17 15:32:44 +0530335 waitForLooper();
John Wang62acae42009-10-08 11:20:23 -0700336 // onStart() method can be passed a null intent
337 // TODO: replace onStart() with onStartCommand()
338 if (intent == null) {
339 return;
340 }
341
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800342 Message msg = mServiceHandler.obtainMessage();
Wink Savillee68857d2014-10-17 15:23:05 -0700343 msg.arg1 = op;
344 msg.arg2 = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800345 switch(msg.arg1) {
346 case OP_CMD:
347 msg.obj = args.getParcelable(CMD_MSG);
348 break;
349 case OP_RESPONSE:
Wink Saville94e982b2014-07-11 07:38:14 -0700350 case OP_CARD_STATUS_CHANGED:
Preeti Ahuja95919342013-10-01 18:18:55 -0700351 case OP_IDLE_SCREEN:
352 case OP_LOCALE_CHANGED:
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +0530353 case OP_ALPHA_NOTIFY:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800354 msg.obj = args;
355 /* falls through */
356 case OP_LAUNCH_APP:
357 case OP_END_SESSION:
358 case OP_BOOT_COMPLETED:
359 break;
360 default:
361 return;
362 }
363 mServiceHandler.sendMessage(msg);
364 }
365
366 @Override
367 public void onDestroy() {
Wink Savillee68857d2014-10-17 15:23:05 -0700368 CatLog.d(LOG_TAG, "onDestroy()");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800369 waitForLooper();
370 mServiceLooper.quit();
371 }
372
373 @Override
374 public IBinder onBind(Intent intent) {
375 return null;
376 }
377
378 public void run() {
379 Looper.prepare();
380
381 mServiceLooper = Looper.myLooper();
382 mServiceHandler = new ServiceHandler();
383
384 Looper.loop();
385 }
386
387 /*
388 * Package api used by StkMenuActivity to indicate if its on the foreground.
389 */
Wink Savillee68857d2014-10-17 15:23:05 -0700390 void indicateMenuVisibility(boolean visibility, int slotId) {
391 if (slotId >= 0 && slotId < mSimCount) {
392 mStkContext[slotId].mMenuIsVisible = visibility;
393 }
394 }
395
Preeti Ahuja95919342013-10-01 18:18:55 -0700396 /*
397 * Package api used by StkDialogActivity to indicate if its on the foreground.
398 */
399 void setDisplayTextDlgVisibility(boolean visibility, int slotId) {
400 if (slotId >= 0 && slotId < mSimCount) {
401 mStkContext[slotId].mDisplayTextDlgIsVisibile = visibility;
402 }
403 }
404
Wink Savillee68857d2014-10-17 15:23:05 -0700405 boolean isInputPending(int slotId) {
406 if (slotId >= 0 && slotId < mSimCount) {
407 CatLog.d(LOG_TAG, "isInputFinishBySrv: " + mStkContext[slotId].mIsInputPending);
408 return mStkContext[slotId].mIsInputPending;
409 }
410 return false;
411 }
412
413 boolean isMenuPending(int slotId) {
414 if (slotId >= 0 && slotId < mSimCount) {
415 CatLog.d(LOG_TAG, "isMenuPending: " + mStkContext[slotId].mIsMenuPending);
416 return mStkContext[slotId].mIsMenuPending;
417 }
418 return false;
419 }
420
421 boolean isDialogPending(int slotId) {
422 if (slotId >= 0 && slotId < mSimCount) {
423 CatLog.d(LOG_TAG, "isDialogPending: " + mStkContext[slotId].mIsDialogPending);
424 return mStkContext[slotId].mIsDialogPending;
425 }
426 return false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800427 }
428
429 /*
430 * Package api used by StkMenuActivity to get its Menu parameter.
431 */
Wink Savillee68857d2014-10-17 15:23:05 -0700432 Menu getMenu(int slotId) {
433 CatLog.d(LOG_TAG, "StkAppService, getMenu, sim id: " + slotId);
434 if (slotId >=0 && slotId < mSimCount) {
435 return mStkContext[slotId].mCurrentMenu;
436 } else {
437 return null;
438 }
439 }
440
441 /*
442 * Package api used by StkMenuActivity to get its Main Menu parameter.
443 */
444 Menu getMainMenu(int slotId) {
445 CatLog.d(LOG_TAG, "StkAppService, getMainMenu, sim id: " + slotId);
446 if (slotId >=0 && slotId < mSimCount) {
447 return mStkContext[slotId].mMainCmd.getMenu();
448 } else {
449 return null;
450 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800451 }
452
453 /*
454 * Package api used by UI Activities and Dialogs to communicate directly
455 * with the service to deliver state information and parameters.
456 */
457 static StkAppService getInstance() {
458 return sInstance;
459 }
460
461 private void waitForLooper() {
462 while (mServiceHandler == null) {
463 synchronized (this) {
464 try {
465 wait(100);
466 } catch (InterruptedException e) {
467 }
468 }
469 }
470 }
471
472 private final class ServiceHandler extends Handler {
473 @Override
474 public void handleMessage(Message msg) {
Wink Savillee68857d2014-10-17 15:23:05 -0700475 if(null == msg) {
476 CatLog.d(LOG_TAG, "ServiceHandler handleMessage msg is null");
477 return;
478 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800479 int opcode = msg.arg1;
Wink Savillee68857d2014-10-17 15:23:05 -0700480 int slotId = msg.arg2;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800481
Wink Savillee68857d2014-10-17 15:23:05 -0700482 CatLog.d(LOG_TAG, "handleMessage opcode[" + opcode + "], sim id[" + slotId + "]");
483 if (opcode == OP_CMD && msg.obj != null &&
484 ((CatCmdMessage)msg.obj).getCmdType()!= null) {
485 CatLog.d(LOG_TAG, "cmdName[" + ((CatCmdMessage)msg.obj).getCmdType().name() + "]");
486 }
487 mStkContext[slotId].mOpCode = opcode;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800488 switch (opcode) {
489 case OP_LAUNCH_APP:
Wink Savillee68857d2014-10-17 15:23:05 -0700490 if (mStkContext[slotId].mMainCmd == null) {
491 CatLog.d(LOG_TAG, "mMainCmd is null");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800492 // nothing todo when no SET UP MENU command didn't arrive.
493 return;
494 }
Wink Savillee68857d2014-10-17 15:23:05 -0700495 CatLog.d(LOG_TAG, "handleMessage OP_LAUNCH_APP - mCmdInProgress[" +
496 mStkContext[slotId].mCmdInProgress + "]");
497
498 //If there is a pending activity for the slot id,
499 //just finish it and create a new one to handle the pending command.
500 cleanUpInstanceStackBySlot(slotId);
501
502 //Clean up all other activities in stack.
503 for (int i = 0; i < mSimCount; i++) {
504 if (i != slotId && mStkContext[i].mCurrentCmd != null) {
505 Activity otherAct = mStkContext[i].getPendingActivityInstance();
506 Activity otherDal = mStkContext[i].getPendingDialogInstance();
507 Activity otherMainMenu = mStkContext[i].getMainActivityInstance();
508 if (otherAct != null) {
509 CatLog.d(LOG_TAG, "finish pending otherAct and send SE. slot: " + i);
510 // Send end session for the pending proactive command of slot i in
511 // onDestroy of the activity.
512 // Set mBackGroundTRSent to true for ignoring to show the main menu
513 // for the following end session event.
514 mStkContext[i].mBackGroundTRSent = true;
515 otherAct.finish();
516 mStkContext[i].mActivityInstance = null;
517 }
518 if (otherDal != null) {
519 CatLog.d(LOG_TAG, "finish pending otherDal and send TR for the dialog");
520 mStkContext[i].mBackGroundTRSent = true;
521 otherDal.finish();
522 mStkContext[i].mDialogInstance = null;
523 }
524 if (otherMainMenu != null) {
525 CatLog.d(LOG_TAG, "finish pending otherMainMenu.");
526 otherMainMenu.finish();
527 mStkContext[i].mMainActivityInstance = null;
528 }
529 }
530 }
531 CatLog.d(LOG_TAG, "Current cmd type: " +
532 mStkContext[slotId].mCurrentCmd.getCmdType());
533 //Restore the last command from stack by slot id.
534 restoreInstanceFromStackBySlot(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800535 break;
536 case OP_CMD:
Wink Savillee68857d2014-10-17 15:23:05 -0700537 CatLog.d(LOG_TAG, "[OP_CMD]");
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700538 CatCmdMessage cmdMsg = (CatCmdMessage) msg.obj;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800539 // There are two types of commands:
540 // 1. Interactive - user's response is required.
541 // 2. Informative - display a message, no interaction with the user.
542 //
Wink Saville79085fc2009-06-09 10:27:23 -0700543 // Informative commands can be handled immediately without any delay.
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800544 // Interactive commands can't override each other. So if a command
545 // is already in progress, we need to queue the next command until
546 // the user has responded or a timeout expired.
547 if (!isCmdInteractive(cmdMsg)) {
Wink Savillee68857d2014-10-17 15:23:05 -0700548 handleCmd(cmdMsg, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800549 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700550 if (!mStkContext[slotId].mCmdInProgress) {
551 mStkContext[slotId].mCmdInProgress = true;
552 handleCmd((CatCmdMessage) msg.obj, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800553 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700554 CatLog.d(LOG_TAG, "[Interactive][in progress]");
555 mStkContext[slotId].mCmdsQ.addLast(new DelayedCmd(OP_CMD,
556 (CatCmdMessage) msg.obj, slotId));
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800557 }
558 }
559 break;
560 case OP_RESPONSE:
Preeti Ahuja414bc412013-06-25 19:31:49 -0700561 handleCmdResponse((Bundle) msg.obj, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800562 // call delayed commands if needed.
Wink Savillee68857d2014-10-17 15:23:05 -0700563 if (mStkContext[slotId].mCmdsQ.size() != 0) {
564 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800565 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700566 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800567 }
Preeti Ahuja414bc412013-06-25 19:31:49 -0700568 //reset mIsDisplayTextPending after sending the response.
569 mStkContext[slotId].mIsDisplayTextPending = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800570 break;
571 case OP_END_SESSION:
Wink Savillee68857d2014-10-17 15:23:05 -0700572 if (!mStkContext[slotId].mCmdInProgress) {
573 mStkContext[slotId].mCmdInProgress = true;
574 handleSessionEnd(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800575 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700576 mStkContext[slotId].mCmdsQ.addLast(
577 new DelayedCmd(OP_END_SESSION, null, slotId));
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800578 }
579 break;
580 case OP_BOOT_COMPLETED:
Wink Savillee68857d2014-10-17 15:23:05 -0700581 CatLog.d(LOG_TAG, " OP_BOOT_COMPLETED");
582 int i = 0;
583 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
584 if (mStkContext[i].mMainCmd != null) {
585 break;
586 }
587 }
588 if (i == mSimCount) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800589 StkAppInstaller.unInstall(mContext);
590 }
591 break;
592 case OP_DELAYED_MSG:
Wink Savillee68857d2014-10-17 15:23:05 -0700593 handleDelayedCmd(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800594 break;
Wink Saville94e982b2014-07-11 07:38:14 -0700595 case OP_CARD_STATUS_CHANGED:
Wink Savillee68857d2014-10-17 15:23:05 -0700596 CatLog.d(LOG_TAG, "Card/Icc Status change received");
597 handleCardStatusChangeAndIccRefresh((Bundle) msg.obj, slotId);
598 break;
599 case OP_SET_ACT_INST:
600 Activity act = new Activity();
601 act = (Activity) msg.obj;
602 CatLog.d(LOG_TAG, "Set activity instance. " + act);
603 mStkContext[slotId].mActivityInstance = act;
604 break;
605 case OP_SET_DAL_INST:
606 Activity dal = new Activity();
607 CatLog.d(LOG_TAG, "Set dialog instance. " + dal);
608 dal = (Activity) msg.obj;
609 mStkContext[slotId].mDialogInstance = dal;
610 break;
611 case OP_SET_MAINACT_INST:
612 Activity mainAct = new Activity();
613 mainAct = (Activity) msg.obj;
614 CatLog.d(LOG_TAG, "Set activity instance. " + mainAct);
615 mStkContext[slotId].mMainActivityInstance = mainAct;
Wink Saville94e982b2014-07-11 07:38:14 -0700616 break;
Preeti Ahuja95919342013-10-01 18:18:55 -0700617 case OP_IDLE_SCREEN:
618 for (int slot = 0; slot < mSimCount; slot++) {
619 if (mStkContext[slot] != null) {
620 handleScreenStatus((Bundle) msg.obj, slot);
621 }
622 }
623 break;
624 case OP_LOCALE_CHANGED:
625 CatLog.d(this, "Locale Changed");
626 checkForSetupEvent(LANGUAGE_SELECTION_EVENT,(Bundle) msg.obj, slotId);
627 break;
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +0530628 case OP_ALPHA_NOTIFY:
629 handleAlphaNotify((Bundle) msg.obj);
630 break;
Wink Saville94e982b2014-07-11 07:38:14 -0700631 }
632 }
633
Wink Savillee68857d2014-10-17 15:23:05 -0700634 private void handleCardStatusChangeAndIccRefresh(Bundle args, int slotId) {
Wink Saville94e982b2014-07-11 07:38:14 -0700635 boolean cardStatus = args.getBoolean(AppInterface.CARD_STATUS);
636
Wink Savillee68857d2014-10-17 15:23:05 -0700637 CatLog.d(LOG_TAG, "CardStatus: " + cardStatus);
Wink Saville94e982b2014-07-11 07:38:14 -0700638 if (cardStatus == false) {
Wink Savillee68857d2014-10-17 15:23:05 -0700639 CatLog.d(LOG_TAG, "CARD is ABSENT");
Wink Saville94e982b2014-07-11 07:38:14 -0700640 // Uninstall STKAPP, Clear Idle text, Stop StkAppService
Wink Savillee68857d2014-10-17 15:23:05 -0700641 mNotificationManager.cancel(getNotificationId(slotId));
642 if (isAllOtherCardsAbsent(slotId)) {
643 CatLog.d(LOG_TAG, "All CARDs are ABSENT");
644 StkAppInstaller.unInstall(mContext);
645 stopSelf();
646 }
Wink Saville94e982b2014-07-11 07:38:14 -0700647 } else {
648 IccRefreshResponse state = new IccRefreshResponse();
649 state.refreshResult = args.getInt(AppInterface.REFRESH_RESULT);
650
Wink Savillee68857d2014-10-17 15:23:05 -0700651 CatLog.d(LOG_TAG, "Icc Refresh Result: "+ state.refreshResult);
Wink Saville94e982b2014-07-11 07:38:14 -0700652 if ((state.refreshResult == IccRefreshResponse.REFRESH_RESULT_INIT) ||
653 (state.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET)) {
654 // Clear Idle Text
Wink Savillee68857d2014-10-17 15:23:05 -0700655 mNotificationManager.cancel(getNotificationId(slotId));
Wink Saville94e982b2014-07-11 07:38:14 -0700656 }
657
658 if (state.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET) {
659 // Uninstall STkmenu
Wink Savillee68857d2014-10-17 15:23:05 -0700660 if (isAllOtherCardsAbsent(slotId)) {
661 StkAppInstaller.unInstall(mContext);
662 }
663 mStkContext[slotId].mCurrentMenu = null;
664 mStkContext[slotId].mMainCmd = null;
Wink Saville94e982b2014-07-11 07:38:14 -0700665 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800666 }
667 }
668 }
Wink Savillee68857d2014-10-17 15:23:05 -0700669 /*
670 * Check if all SIMs are absent except the id of slot equals "slotId".
671 */
672 private boolean isAllOtherCardsAbsent(int slotId) {
673 TelephonyManager mTm = (TelephonyManager) mContext.getSystemService(
674 Context.TELEPHONY_SERVICE);
675 int i = 0;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800676
Wink Savillee68857d2014-10-17 15:23:05 -0700677 for (i = 0; i < mSimCount; i++) {
678 if (i != slotId && mTm.hasIccCard(i)) {
679 break;
680 }
681 }
682 if (i == mSimCount) {
683 return true;
684 } else {
685 return false;
686 }
687 }
Preeti Ahuja95919342013-10-01 18:18:55 -0700688
689 private void handleScreenStatus(Bundle args, int slotId) {
690 mStkContext[slotId].mScreenIdle = args.getBoolean(SCREEN_STATUS);
691
692 // If the idle screen event is present in the list need to send the
693 // response to SIM.
694 if (mStkContext[slotId].mScreenIdle) {
695 CatLog.d(this, "Need to send IDLE SCREEN Available event to SIM");
696 checkForSetupEvent(IDLE_SCREEN_AVAILABLE_EVENT, null, slotId);
697 }
698 if (mStkContext[slotId].mIdleModeTextCmd != null && mStkContext[slotId].mScreenIdle) {
699 launchIdleText(slotId);
700 }
Preeti Ahuja414bc412013-06-25 19:31:49 -0700701 // Show user the display text or send screen busy response
702 // if previous display text command is pending.
703 if (mStkContext[slotId].mIsDisplayTextPending) {
Preeti Ahuja95919342013-10-01 18:18:55 -0700704 if (!mStkContext[slotId].mScreenIdle) {
705 sendScreenBusyResponse(slotId);
706 } else {
707 launchTextDialog(slotId);
708 }
Preeti Ahuja414bc412013-06-25 19:31:49 -0700709 mStkContext[slotId].mIsDisplayTextPending = false;
Preeti Ahuja95919342013-10-01 18:18:55 -0700710 // If an idle text proactive command is set then the
711 // request for getting screen status still holds true.
712 if (mStkContext[slotId].mIdleModeTextCmd == null) {
713 Intent StkIntent = new Intent(AppInterface.CHECK_SCREEN_IDLE_ACTION);
714 StkIntent.putExtra(SCREEN_STATUS_REQUEST, false);
715 sendBroadcast(StkIntent);
716 }
717 }
718 }
719
720 private void sendScreenBusyResponse(int slotId) {
721 if (mStkContext[slotId].mCurrentCmd == null) {
722 return;
723 }
724 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentCmd);
725 CatLog.d(this, "SCREEN_BUSY");
726 resMsg.setResultCode(ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS);
727 mStkService[slotId].onCmdResponse(resMsg);
Preeti Ahuja95919342013-10-01 18:18:55 -0700728 if (mStkContext[slotId].mCmdsQ.size() != 0) {
729 callDelayedMsg(slotId);
730 } else {
731 mStkContext[slotId].mCmdInProgress = false;
732 }
733 }
734
735 private void sendResponse(int resId, int slotId, boolean confirm) {
736 Message msg = mServiceHandler.obtainMessage();
737 msg.arg1 = OP_RESPONSE;
738 Bundle args = new Bundle();
739 args.putInt(StkAppService.RES_ID, resId);
740 args.putInt(SLOT_ID, slotId);
741 args.putBoolean(StkAppService.CONFIRMATION, confirm);
742 msg.obj = args;
743 mServiceHandler.sendMessage(msg);
744 }
745
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700746 private boolean isCmdInteractive(CatCmdMessage cmd) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800747 switch (cmd.getCmdType()) {
748 case SEND_DTMF:
749 case SEND_SMS:
750 case SEND_SS:
751 case SEND_USSD:
752 case SET_UP_IDLE_MODE_TEXT:
753 case SET_UP_MENU:
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500754 case CLOSE_CHANNEL:
755 case RECEIVE_DATA:
756 case SEND_DATA:
Preeti Ahuja95919342013-10-01 18:18:55 -0700757 case SET_UP_EVENT_LIST:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800758 return false;
759 }
760
761 return true;
762 }
763
Wink Savillee68857d2014-10-17 15:23:05 -0700764 private void handleDelayedCmd(int slotId) {
765 CatLog.d(LOG_TAG, "handleDelayedCmd, slotId: " + slotId);
766 if (mStkContext[slotId].mCmdsQ.size() != 0) {
767 DelayedCmd cmd = mStkContext[slotId].mCmdsQ.poll();
768 if (cmd != null) {
769 CatLog.d(LOG_TAG, "handleDelayedCmd - queue size: " +
770 mStkContext[slotId].mCmdsQ.size() +
771 " id: " + cmd.id + "sim id: " + cmd.slotId);
772 switch (cmd.id) {
773 case OP_CMD:
774 handleCmd(cmd.msg, cmd.slotId);
775 break;
776 case OP_END_SESSION:
777 handleSessionEnd(cmd.slotId);
778 break;
779 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800780 }
781 }
782 }
783
Wink Savillee68857d2014-10-17 15:23:05 -0700784 private void callDelayedMsg(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800785 Message msg = mServiceHandler.obtainMessage();
786 msg.arg1 = OP_DELAYED_MSG;
Wink Savillee68857d2014-10-17 15:23:05 -0700787 msg.arg2 = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800788 mServiceHandler.sendMessage(msg);
789 }
790
Wink Savillee68857d2014-10-17 15:23:05 -0700791 private void callSetActivityInstMsg(int inst_type, int slotId, Object obj) {
792 Message msg = mServiceHandler.obtainMessage();
793 msg.obj = obj;
794 msg.arg1 = inst_type;
795 msg.arg2 = slotId;
796 mServiceHandler.sendMessage(msg);
797 }
798
799 private void handleSessionEnd(int slotId) {
800 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
801 CatLog.d(LOG_TAG, "[handleSessionEnd] - mCurrentCmd changed to mMainCmd!.");
802 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mMainCmd;
803 CatLog.d(LOG_TAG, "slotId: " + slotId + ", mMenuState: " +
804 mStkContext[slotId].mMenuState);
805
806 mStkContext[slotId].mIsInputPending = false;
807 mStkContext[slotId].mIsMenuPending = false;
808 mStkContext[slotId].mIsDialogPending = false;
809
810 // We should finish all pending activity if receiving END SESSION command.
811 cleanUpInstanceStackBySlot(slotId);
812
813 if (mStkContext[slotId].mMainCmd == null) {
814 CatLog.d(LOG_TAG, "[handleSessionEnd][mMainCmd is null!]");
815 }
816 mStkContext[slotId].lastSelectedItem = null;
Wink Saville79085fc2009-06-09 10:27:23 -0700817 // In case of SET UP MENU command which removed the app, don't
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800818 // update the current menu member.
Wink Savillee68857d2014-10-17 15:23:05 -0700819 if (mStkContext[slotId].mCurrentMenu != null && mStkContext[slotId].mMainCmd != null) {
820 mStkContext[slotId].mCurrentMenu = mStkContext[slotId].mMainCmd.getMenu();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800821 }
Wink Savillee68857d2014-10-17 15:23:05 -0700822 CatLog.d(LOG_TAG, "[handleSessionEnd][mMenuState]" + mStkContext[slotId].mMenuIsVisible);
823 // In mutiple instance architecture, the main menu for slotId will be finished when user
824 // goes to the Stk menu of the other SIM. So, we should launch a new instance for the
825 // main menu if the main menu instance has been finished.
826 // If the current menu is secondary menu, we should launch main menu.
827 if (StkMenuActivity.STATE_SECONDARY == mStkContext[slotId].mMenuState) {
828 launchMenuActivity(null, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800829 }
Wink Savillee68857d2014-10-17 15:23:05 -0700830 if (mStkContext[slotId].mCmdsQ.size() != 0) {
831 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800832 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700833 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800834 }
835 // In case a launch browser command was just confirmed, launch that url.
Wink Savillee68857d2014-10-17 15:23:05 -0700836 if (mStkContext[slotId].launchBrowser) {
837 mStkContext[slotId].launchBrowser = false;
838 launchBrowser(mStkContext[slotId].mBrowserSettings);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800839 }
840 }
841
Preeti Ahuja95919342013-10-01 18:18:55 -0700842 // returns true if any Stk related activity already has focus on the screen
843 private boolean isTopOfStack() {
844 ActivityManager mAcivityManager = (ActivityManager) mContext
845 .getSystemService(ACTIVITY_SERVICE);
846 String currentPackageName = mAcivityManager.getRunningTasks(1).get(0).topActivity
847 .getPackageName();
848 if (null != currentPackageName) {
849 return currentPackageName.equals(PACKAGE_NAME);
850 }
851
852 return false;
853 }
854
855
Wink Savillee68857d2014-10-17 15:23:05 -0700856 private void handleCmd(CatCmdMessage cmdMsg, int slotId) {
Preeti Ahuja95919342013-10-01 18:18:55 -0700857
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800858 if (cmdMsg == null) {
859 return;
860 }
861 // save local reference for state tracking.
Wink Savillee68857d2014-10-17 15:23:05 -0700862 mStkContext[slotId].mCurrentCmd = cmdMsg;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800863 boolean waitForUsersResponse = true;
864
Wink Savillee68857d2014-10-17 15:23:05 -0700865 mStkContext[slotId].mIsInputPending = false;
866 mStkContext[slotId].mIsMenuPending = false;
867 mStkContext[slotId].mIsDialogPending = false;
868
869 CatLog.d(LOG_TAG,"[handleCmd]" + cmdMsg.getCmdType().name());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800870 switch (cmdMsg.getCmdType()) {
871 case DISPLAY_TEXT:
872 TextMessage msg = cmdMsg.geTextMessage();
Jeevaka Badrappan854a25c2012-12-01 16:32:03 +0200873 waitForUsersResponse = msg.responseNeeded;
Wink Savillee68857d2014-10-17 15:23:05 -0700874 if (mStkContext[slotId].lastSelectedItem != null) {
875 msg.title = mStkContext[slotId].lastSelectedItem;
876 } else if (mStkContext[slotId].mMainCmd != null){
877 msg.title = mStkContext[slotId].mMainCmd.getMenu().title;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800878 } else {
879 // TODO: get the carrier name from the SIM
880 msg.title = "";
881 }
Preeti Ahuja95919342013-10-01 18:18:55 -0700882
883 //If the device is not displaying an STK related dialogue and we
884 //receive a low priority Display Text command then send a screen
885 //busy terminal response with out displaying the message. Otherwise
886 //display the message. The existing displayed message shall be updated
887 //with the new display text proactive command (Refer to ETSI TS 102 384
888 //section 27.22.4.1.4.4.2).
889 if (!(msg.isHighPriority || mStkContext[slotId].mMenuIsVisible
890 || mStkContext[slotId].mDisplayTextDlgIsVisibile || isTopOfStack())) {
891 Intent StkIntent = new Intent(AppInterface.CHECK_SCREEN_IDLE_ACTION);
892 StkIntent.putExtra(SCREEN_STATUS_REQUEST, true);
893 sendBroadcast(StkIntent);
Preeti Ahuja414bc412013-06-25 19:31:49 -0700894 mStkContext[slotId].mIsDisplayTextPending = true;
Preeti Ahuja95919342013-10-01 18:18:55 -0700895 } else {
896 launchTextDialog(slotId);
897 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800898 break;
899 case SELECT_ITEM:
Wink Savillee68857d2014-10-17 15:23:05 -0700900 CatLog.d(LOG_TAG, "SELECT_ITEM +");
901 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
902 mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
903 launchMenuActivity(cmdMsg.getMenu(), slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800904 break;
905 case SET_UP_MENU:
Wink Savillee68857d2014-10-17 15:23:05 -0700906 mStkContext[slotId].mCmdInProgress = false;
907 mStkContext[slotId].mMainCmd = mStkContext[slotId].mCurrentCmd;
908 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
909 mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
910 CatLog.d(LOG_TAG, "SET_UP_MENU [" + removeMenu(slotId) + "]");
911
912 if (removeMenu(slotId)) {
913 int i = 0;
914 CatLog.d(LOG_TAG, "removeMenu() - Uninstall App");
915 mStkContext[slotId].mCurrentMenu = null;
Preeti Ahuja95919342013-10-01 18:18:55 -0700916 mStkContext[slotId].mMainCmd = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700917 //Check other setup menu state. If all setup menu are removed, uninstall apk.
918 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
919 if (i != slotId
920 && (mStkContext[slotId].mSetupMenuState == STATE_UNKNOWN
921 || mStkContext[slotId].mSetupMenuState == STATE_EXIST)) {
922 CatLog.d(LOG_TAG, "Not Uninstall App:" + i + ","
923 + mStkContext[slotId].mSetupMenuState);
924 break;
925 }
926 }
927 if (i == mSimCount) {
928 StkAppInstaller.unInstall(mContext);
929 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800930 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700931 CatLog.d(LOG_TAG, "install App");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800932 StkAppInstaller.install(mContext);
933 }
Wink Savillee68857d2014-10-17 15:23:05 -0700934 if (mStkContext[slotId].mMenuIsVisible) {
935 launchMenuActivity(null, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800936 }
937 break;
938 case GET_INPUT:
939 case GET_INKEY:
Wink Savillee68857d2014-10-17 15:23:05 -0700940 launchInputActivity(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800941 break;
942 case SET_UP_IDLE_MODE_TEXT:
943 waitForUsersResponse = false;
Preeti Ahuja95919342013-10-01 18:18:55 -0700944 mStkContext[slotId].mIdleModeTextCmd = mStkContext[slotId].mCurrentCmd;
945 TextMessage idleModeText = mStkContext[slotId].mCurrentCmd.geTextMessage();
946 // Send intent to ActivityManagerService to get the screen status
947 Intent idleStkIntent = new Intent(AppInterface.CHECK_SCREEN_IDLE_ACTION);
948 if (idleModeText == null) {
949 launchIdleText(slotId);
950 mStkContext[slotId].mIdleModeTextCmd = null;
951 }
952 CatLog.d(this, "set up idle mode");
953 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
954 sendBroadcast(idleStkIntent);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800955 break;
956 case SEND_DTMF:
957 case SEND_SMS:
958 case SEND_SS:
959 case SEND_USSD:
Preeti Ahuja95919342013-10-01 18:18:55 -0700960 case GET_CHANNEL_STATUS:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800961 waitForUsersResponse = false;
Wink Savillee68857d2014-10-17 15:23:05 -0700962 launchEventMessage(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800963 break;
964 case LAUNCH_BROWSER:
Wink Savillee68857d2014-10-17 15:23:05 -0700965 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.geTextMessage(), slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800966 break;
967 case SET_UP_CALL:
Wink Savillee68857d2014-10-17 15:23:05 -0700968 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.getCallSettings()
969 .confirmMsg, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800970 break;
971 case PLAY_TONE:
Wink Savillee68857d2014-10-17 15:23:05 -0700972 launchToneDialog(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800973 break;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500974 case OPEN_CHANNEL:
Wink Savillee68857d2014-10-17 15:23:05 -0700975 launchOpenChannelDialog(slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500976 break;
977 case CLOSE_CHANNEL:
978 case RECEIVE_DATA:
979 case SEND_DATA:
Wink Savillee68857d2014-10-17 15:23:05 -0700980 TextMessage m = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500981
982 if ((m != null) && (m.text == null)) {
983 switch(cmdMsg.getCmdType()) {
984 case CLOSE_CHANNEL:
985 m.text = getResources().getString(R.string.default_close_channel_msg);
986 break;
987 case RECEIVE_DATA:
988 m.text = getResources().getString(R.string.default_receive_data_msg);
989 break;
990 case SEND_DATA:
991 m.text = getResources().getString(R.string.default_send_data_msg);
992 break;
993 }
994 }
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -0700995 /*
996 * Display indication in the form of a toast to the user if required.
997 */
Wink Savillee68857d2014-10-17 15:23:05 -0700998 launchEventMessage(slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500999 break;
Preeti Ahuja95919342013-10-01 18:18:55 -07001000 case SET_UP_EVENT_LIST:
1001 mStkContext[slotId].mSetupEventListSettings =
1002 mStkContext[slotId].mCurrentCmd.getSetEventList();
1003 mStkContext[slotId].mCurrentSetupEventCmd = mStkContext[slotId].mCurrentCmd;
1004 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
1005 if ((mStkContext[slotId].mIdleModeTextCmd == null)
Preeti Ahuja414bc412013-06-25 19:31:49 -07001006 && (!mStkContext[slotId].mIsDisplayTextPending)) {
Preeti Ahuja95919342013-10-01 18:18:55 -07001007 for (int i : mStkContext[slotId].mSetupEventListSettings.eventList) {
1008 if (i == IDLE_SCREEN_AVAILABLE_EVENT) {
1009 CatLog.d(this," IDLE_SCREEN_AVAILABLE_EVENT present in List");
1010 // Request ActivityManagerService to get the screen status
1011 Intent StkIntent = new Intent(AppInterface.CHECK_SCREEN_IDLE_ACTION);
1012 StkIntent.putExtra(SCREEN_STATUS_REQUEST, true);
1013 sendBroadcast(StkIntent);
1014 break;
1015 }
1016 }
1017 }
1018 break;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001019 }
1020
1021 if (!waitForUsersResponse) {
Wink Savillee68857d2014-10-17 15:23:05 -07001022 if (mStkContext[slotId].mCmdsQ.size() != 0) {
1023 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001024 } else {
Wink Savillee68857d2014-10-17 15:23:05 -07001025 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001026 }
1027 }
1028 }
1029
Wink Savillee68857d2014-10-17 15:23:05 -07001030 private void handleCmdResponse(Bundle args, int slotId) {
1031 CatLog.d(LOG_TAG, "handleCmdResponse, sim id: " + slotId);
1032 if (mStkContext[slotId].mCurrentCmd == null) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001033 return;
1034 }
Wink Savillee68857d2014-10-17 15:23:05 -07001035
1036 if (mStkService[slotId] == null) {
1037 if(null != UiccController.getInstance() &&
1038 null != UiccController.getInstance().getUiccCard(slotId)) {
1039 mStkService[slotId] = UiccController.getInstance().getUiccCard(slotId)
1040 .getCatService();
1041 } else {
1042 CatLog.d(LOG_TAG, "Null instance: [" + UiccController.getInstance() +
1043 "],["+UiccController.getInstance().getUiccCard(slotId)+"]");
1044 }
1045 if (mStkService[slotId] == null) {
Alex Yakavenkad8e2ecd2012-04-20 17:10:15 -07001046 // This should never happen (we should be responding only to a message
1047 // that arrived from StkService). It has to exist by this time
Wink Savillee68857d2014-10-17 15:23:05 -07001048 CatLog.d(LOG_TAG, "Exception! mStkService is null when we need to send response.");
Alex Yakavenkad8e2ecd2012-04-20 17:10:15 -07001049 throw new RuntimeException("mStkService is null when we need to send response");
1050 }
1051 }
1052
Wink Savillee68857d2014-10-17 15:23:05 -07001053 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentCmd);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001054
1055 // set result code
1056 boolean helpRequired = args.getBoolean(HELP, false);
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001057 boolean confirmed = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001058
1059 switch(args.getInt(RES_ID)) {
1060 case RES_ID_MENU_SELECTION:
Wink Savillee68857d2014-10-17 15:23:05 -07001061 CatLog.d(LOG_TAG, "MENU_SELECTION=" + mStkContext[slotId].
1062 mCurrentMenuCmd.getCmdType());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001063 int menuSelection = args.getInt(MENU_SELECTION);
Wink Savillee68857d2014-10-17 15:23:05 -07001064 switch(mStkContext[slotId].mCurrentMenuCmd.getCmdType()) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001065 case SET_UP_MENU:
1066 case SELECT_ITEM:
Wink Savillee68857d2014-10-17 15:23:05 -07001067 mStkContext[slotId].lastSelectedItem = getItemName(menuSelection, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001068 if (helpRequired) {
1069 resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
1070 } else {
1071 resMsg.setResultCode(ResultCode.OK);
1072 }
1073 resMsg.setMenuSelection(menuSelection);
1074 break;
1075 }
1076 break;
1077 case RES_ID_INPUT:
Wink Savillee68857d2014-10-17 15:23:05 -07001078 CatLog.d(LOG_TAG, "RES_ID_INPUT");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001079 String input = args.getString(INPUT);
Wink Savillee68857d2014-10-17 15:23:05 -07001080 if (input != null && (null != mStkContext[slotId].mCurrentCmd.geInput()) &&
1081 (mStkContext[slotId].mCurrentCmd.geInput().yesNo)) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001082 boolean yesNoSelection = input
1083 .equals(StkInputActivity.YES_STR_RESPONSE);
1084 resMsg.setYesNo(yesNoSelection);
1085 } else {
1086 if (helpRequired) {
1087 resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
1088 } else {
1089 resMsg.setResultCode(ResultCode.OK);
1090 resMsg.setInput(input);
1091 }
1092 }
1093 break;
1094 case RES_ID_CONFIRM:
Alex Yakavenkad41f1d92010-07-12 14:13:13 -07001095 CatLog.d(this, "RES_ID_CONFIRM");
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001096 confirmed = args.getBoolean(CONFIRMATION);
Wink Savillee68857d2014-10-17 15:23:05 -07001097 switch (mStkContext[slotId].mCurrentCmd.getCmdType()) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001098 case DISPLAY_TEXT:
1099 resMsg.setResultCode(confirmed ? ResultCode.OK
Preeti Ahuja95919342013-10-01 18:18:55 -07001100 : ResultCode.UICC_SESSION_TERM_BY_USER);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001101 break;
1102 case LAUNCH_BROWSER:
1103 resMsg.setResultCode(confirmed ? ResultCode.OK
1104 : ResultCode.UICC_SESSION_TERM_BY_USER);
1105 if (confirmed) {
Wink Savillee68857d2014-10-17 15:23:05 -07001106 mStkContext[slotId].launchBrowser = true;
1107 mStkContext[slotId].mBrowserSettings =
1108 mStkContext[slotId].mCurrentCmd.getBrowserSettings();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001109 }
1110 break;
1111 case SET_UP_CALL:
1112 resMsg.setResultCode(ResultCode.OK);
1113 resMsg.setConfirmation(confirmed);
1114 if (confirmed) {
Wink Savillee68857d2014-10-17 15:23:05 -07001115 launchEventMessage(slotId,
1116 mStkContext[slotId].mCurrentCmd.getCallSettings().callMsg);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001117 }
1118 break;
1119 }
1120 break;
1121 case RES_ID_DONE:
1122 resMsg.setResultCode(ResultCode.OK);
1123 break;
1124 case RES_ID_BACKWARD:
Wink Savillee68857d2014-10-17 15:23:05 -07001125 CatLog.d(LOG_TAG, "RES_ID_BACKWARD");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001126 resMsg.setResultCode(ResultCode.BACKWARD_MOVE_BY_USER);
1127 break;
1128 case RES_ID_END_SESSION:
Wink Savillee68857d2014-10-17 15:23:05 -07001129 CatLog.d(LOG_TAG, "RES_ID_END_SESSION");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001130 resMsg.setResultCode(ResultCode.UICC_SESSION_TERM_BY_USER);
1131 break;
1132 case RES_ID_TIMEOUT:
Wink Savillee68857d2014-10-17 15:23:05 -07001133 CatLog.d(LOG_TAG, "RES_ID_TIMEOUT");
Naveen Kallad5176892009-11-30 12:45:29 -08001134 // GCF test-case 27.22.4.1.1 Expected Sequence 1.5 (DISPLAY TEXT,
1135 // Clear message after delay, successful) expects result code OK.
1136 // If the command qualifier specifies no user response is required
1137 // then send OK instead of NO_RESPONSE_FROM_USER
Wink Savillee68857d2014-10-17 15:23:05 -07001138 if ((mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1139 AppInterface.CommandType.DISPLAY_TEXT.value())
1140 && (mStkContext[slotId].mCurrentCmd.geTextMessage().userClear == false)) {
Naveen Kallad5176892009-11-30 12:45:29 -08001141 resMsg.setResultCode(ResultCode.OK);
1142 } else {
1143 resMsg.setResultCode(ResultCode.NO_RESPONSE_FROM_USER);
1144 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001145 break;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001146 case RES_ID_CHOICE:
1147 int choice = args.getInt(CHOICE);
1148 CatLog.d(this, "User Choice=" + choice);
1149 switch (choice) {
1150 case YES:
1151 resMsg.setResultCode(ResultCode.OK);
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001152 confirmed = true;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001153 break;
1154 case NO:
1155 resMsg.setResultCode(ResultCode.USER_NOT_ACCEPT);
1156 break;
1157 }
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001158
Wink Savillee68857d2014-10-17 15:23:05 -07001159 if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1160 AppInterface.CommandType.OPEN_CHANNEL.value()) {
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001161 resMsg.setConfirmation(confirmed);
1162 }
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001163 break;
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001164
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001165 default:
Wink Savillee68857d2014-10-17 15:23:05 -07001166 CatLog.d(LOG_TAG, "Unknown result id");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001167 return;
1168 }
Wink Savillee68857d2014-10-17 15:23:05 -07001169
1170 if (null != mStkContext[slotId].mCurrentCmd &&
1171 null != mStkContext[slotId].mCurrentCmd.getCmdType()) {
1172 CatLog.d(LOG_TAG, "handleCmdResponse- cmdName[" +
1173 mStkContext[slotId].mCurrentCmd.getCmdType().name() + "]");
1174 }
1175 mStkService[slotId].onCmdResponse(resMsg);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001176 }
1177
1178 /**
1179 * Returns 0 or FLAG_ACTIVITY_NO_USER_ACTION, 0 means the user initiated the action.
1180 *
1181 * @param userAction If the userAction is yes then we always return 0 otherwise
1182 * mMenuIsVisible is used to determine what to return. If mMenuIsVisible is true
1183 * then we are the foreground app and we'll return 0 as from our perspective a
1184 * user action did cause. If it's false than we aren't the foreground app and
1185 * FLAG_ACTIVITY_NO_USER_ACTION is returned.
Wink Saville79085fc2009-06-09 10:27:23 -07001186 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001187 * @return 0 or FLAG_ACTIVITY_NO_USER_ACTION
1188 */
Wink Savillee68857d2014-10-17 15:23:05 -07001189 private int getFlagActivityNoUserAction(InitiatedByUserAction userAction, int slotId) {
1190 return ((userAction == InitiatedByUserAction.yes) | mStkContext[slotId].mMenuIsVisible)
1191 ? 0 : Intent.FLAG_ACTIVITY_NO_USER_ACTION;
1192 }
1193 /**
1194 * This method is used for cleaning up pending instances in stack.
1195 */
1196 private void cleanUpInstanceStackBySlot(int slotId) {
1197 Activity activity = mStkContext[slotId].getPendingActivityInstance();
1198 Activity dialog = mStkContext[slotId].getPendingDialogInstance();
1199 CatLog.d(LOG_TAG, "cleanUpInstanceStackBySlot slotId: " + slotId);
1200 if (activity != null) {
1201 CatLog.d(LOG_TAG, "current cmd type: " +
1202 mStkContext[slotId].mCurrentCmd.getCmdType());
1203 if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1204 AppInterface.CommandType.GET_INPUT.value() ||
1205 mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1206 AppInterface.CommandType.GET_INKEY.value()) {
1207 mStkContext[slotId].mIsInputPending = true;
1208 } else if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1209 AppInterface.CommandType.SET_UP_MENU.value() ||
1210 mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1211 AppInterface.CommandType.SELECT_ITEM.value()) {
1212 mStkContext[slotId].mIsMenuPending = true;
1213 } else {
1214 }
1215 CatLog.d(LOG_TAG, "finish pending activity.");
1216 activity.finish();
1217 mStkContext[slotId].mActivityInstance = null;
1218 }
1219 if (dialog != null) {
1220 CatLog.d(LOG_TAG, "finish pending dialog.");
1221 mStkContext[slotId].mIsDialogPending = true;
1222 dialog.finish();
1223 mStkContext[slotId].mDialogInstance = null;
1224 }
1225 }
1226 /**
1227 * This method is used for restoring pending instances from stack.
1228 */
1229 private void restoreInstanceFromStackBySlot(int slotId) {
1230 AppInterface.CommandType cmdType = mStkContext[slotId].mCurrentCmd.getCmdType();
1231
1232 CatLog.d(LOG_TAG, "restoreInstanceFromStackBySlot cmdType : " + cmdType);
1233 switch(cmdType) {
1234 case GET_INPUT:
1235 case GET_INKEY:
1236 launchInputActivity(slotId);
1237 //Set mMenuIsVisible to true for showing main menu for
1238 //following session end command.
1239 mStkContext[slotId].mMenuIsVisible = true;
1240 break;
1241 case DISPLAY_TEXT:
1242 launchTextDialog(slotId);
1243 break;
1244 case LAUNCH_BROWSER:
1245 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.geTextMessage(),
1246 slotId);
1247 break;
1248 case OPEN_CHANNEL:
1249 launchOpenChannelDialog(slotId);
1250 break;
1251 case SET_UP_CALL:
1252 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.getCallSettings().
1253 confirmMsg, slotId);
1254 break;
1255 case SET_UP_MENU:
1256 case SELECT_ITEM:
1257 launchMenuActivity(null, slotId);
1258 break;
1259 default:
1260 break;
1261 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001262 }
1263
Wink Savillee68857d2014-10-17 15:23:05 -07001264 private void launchMenuActivity(Menu menu, int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001265 Intent newIntent = new Intent(Intent.ACTION_VIEW);
Wink Savillee68857d2014-10-17 15:23:05 -07001266 String targetActivity = STK_MENU_ACTIVITY_NAME;
1267 String uriString = STK_MENU_URI + System.currentTimeMillis();
1268 //Set unique URI to create a new instance of activity for different slotId.
1269 Uri uriData = Uri.parse(uriString);
1270
1271 CatLog.d(LOG_TAG, "launchMenuActivity, slotId: " + slotId + " , " +
1272 uriData.toString() + " , " + mStkContext[slotId].mOpCode + ", "
1273 + mStkContext[slotId].mMenuState);
1274 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1275 int intentFlags = Intent.FLAG_ACTIVITY_NEW_TASK;
1276
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001277 if (menu == null) {
1278 // We assume this was initiated by the user pressing the tool kit icon
Wink Savillee68857d2014-10-17 15:23:05 -07001279 intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.yes, slotId);
1280 if (mStkContext[slotId].mOpCode == OP_END_SESSION) {
1281 CatLog.d(LOG_TAG, "launchMenuActivity, return OP_END_SESSION");
1282 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
1283 if (mStkContext[slotId].mMainActivityInstance != null) {
1284 CatLog.d(LOG_TAG, "launchMenuActivity, mMainActivityInstance is not null");
1285 return;
1286 }
1287 // If END SESSION is sent that results from the activity is finished by
1288 // stkappservice (line 457), we should igonore to display the stk main menu
1289 // of slot id.
1290 if (mStkContext[slotId].mBackGroundTRSent) {
1291 CatLog.d(LOG_TAG, "launchMenuActivity, ES is triggered by BG.");
1292 mStkContext[slotId].mBackGroundTRSent = false;
1293 return;
1294 }
1295 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001296
Wink Savillee68857d2014-10-17 15:23:05 -07001297 //If the last pending menu is secondary menu, "STATE" should be "STATE_SECONDARY".
1298 //Otherwise, it should be "STATE_MAIN".
1299 if (mStkContext[slotId].mOpCode == OP_LAUNCH_APP &&
1300 mStkContext[slotId].mMenuState == StkMenuActivity.STATE_SECONDARY) {
1301 newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
1302 } else {
1303 newIntent.putExtra("STATE", StkMenuActivity.STATE_MAIN);
1304 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
1305 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001306 } else {
1307 // We don't know and we'll let getFlagActivityNoUserAction decide.
Wink Savillee68857d2014-10-17 15:23:05 -07001308 intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001309 newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
Wink Savillee68857d2014-10-17 15:23:05 -07001310 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_SECONDARY;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001311 }
Wink Savillee68857d2014-10-17 15:23:05 -07001312 newIntent.putExtra(SLOT_ID, slotId);
1313 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001314 newIntent.setFlags(intentFlags);
1315 mContext.startActivity(newIntent);
1316 }
1317
Wink Savillee68857d2014-10-17 15:23:05 -07001318 private void launchInputActivity(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001319 Intent newIntent = new Intent(Intent.ACTION_VIEW);
Wink Savillee68857d2014-10-17 15:23:05 -07001320 String targetActivity = STK_INPUT_ACTIVITY_NAME;
1321 String uriString = STK_INPUT_URI + System.currentTimeMillis();
1322 //Set unique URI to create a new instance of activity for different slotId.
1323 Uri uriData = Uri.parse(uriString);
1324
1325 CatLog.d(LOG_TAG, "launchInputActivity, slotId: " + slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001326 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
Wink Savillee68857d2014-10-17 15:23:05 -07001327 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1328 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1329 newIntent.putExtra("INPUT", mStkContext[slotId].mCurrentCmd.geInput());
1330 newIntent.putExtra(SLOT_ID, slotId);
1331 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001332 mContext.startActivity(newIntent);
1333 }
1334
Wink Savillee68857d2014-10-17 15:23:05 -07001335 private void launchTextDialog(int slotId) {
1336 CatLog.d(LOG_TAG, "launchTextDialog, slotId: " + slotId);
1337 Intent newIntent = new Intent();
1338 String targetActivity = STK_DIALOG_ACTIVITY_NAME;
1339 int action = getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
1340 String uriString = STK_DIALOG_URI + System.currentTimeMillis();
1341 //Set unique URI to create a new instance of activity for different slotId.
1342 Uri uriData = Uri.parse(uriString);
1343 if (newIntent != null) {
1344 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1345 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1346 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
1347 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1348 newIntent.setData(uriData);
1349 newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
1350 newIntent.putExtra(SLOT_ID, slotId);
1351 startActivity(newIntent);
Preeti Ahuja414bc412013-06-25 19:31:49 -07001352 // For display texts with immediate response, send the terminal response
1353 // immediately. responseNeeded will be false, if display text command has
1354 // the immediate response tlv.
1355 if (!mStkContext[slotId].mCurrentCmd.geTextMessage().responseNeeded) {
1356 sendResponse(RES_ID_CONFIRM, slotId, true);
1357 }
Wink Savillee68857d2014-10-17 15:23:05 -07001358 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001359 }
1360
Wink Savillee68857d2014-10-17 15:23:05 -07001361 public boolean isStkDialogActivated(Context context) {
1362 String stkDialogActivity = "com.android.stk.StkDialogActivity";
1363 boolean activated = false;
1364 final ActivityManager am = (ActivityManager) context.getSystemService(
1365 Context.ACTIVITY_SERVICE);
1366 String topActivity = am.getRunningTasks(1).get(0).topActivity.getClassName();
1367
1368 CatLog.d(LOG_TAG, "isStkDialogActivated: " + topActivity);
1369 if (topActivity.equals(stkDialogActivity)) {
1370 activated = true;
1371 }
1372 CatLog.d(LOG_TAG, "activated : " + activated);
1373 return activated;
Johan Hellman3aec01c2011-02-10 10:15:28 +01001374 }
1375
Preeti Ahuja95919342013-10-01 18:18:55 -07001376 private void sendSetUpEventResponse(int event, byte[] addedInfo, int slotId) {
Preeti Ahuja414bc412013-06-25 19:31:49 -07001377 CatLog.d(this, "sendSetUpEventResponse: event : " + event + "slotId = " + slotId);
Preeti Ahuja95919342013-10-01 18:18:55 -07001378
1379 if (mStkContext[slotId].mCurrentSetupEventCmd == null){
1380 CatLog.e(this, "mCurrentSetupEventCmd is null");
1381 return;
1382 }
1383
1384 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentSetupEventCmd);
1385
1386 resMsg.setResultCode(ResultCode.OK);
1387 resMsg.setEventDownload(event, addedInfo);
1388
1389 mStkService[slotId].onCmdResponse(resMsg);
1390 }
1391
1392 private void checkForSetupEvent(int event, Bundle args, int slotId) {
1393 boolean eventPresent = false;
1394 byte[] addedInfo = null;
1395 CatLog.d(this, "Event :" + event);
1396
1397 if (mStkContext[slotId].mSetupEventListSettings != null) {
1398 /* Checks if the event is present in the EventList updated by last
1399 * SetupEventList Proactive Command */
1400 for (int i : mStkContext[slotId].mSetupEventListSettings.eventList) {
1401 if (event == i) {
1402 eventPresent = true;
1403 break;
1404 }
1405 }
1406
1407 /* If Event is present send the response to ICC */
1408 if (eventPresent == true) {
1409 CatLog.d(this, " Event " + event + "exists in the EventList");
1410
1411 switch (event) {
1412 case IDLE_SCREEN_AVAILABLE_EVENT:
1413 sendSetUpEventResponse(event, addedInfo, slotId);
1414 removeSetUpEvent(event, slotId);
1415 break;
1416 case LANGUAGE_SELECTION_EVENT:
1417 String language = mContext
1418 .getResources().getConfiguration().locale.getLanguage();
1419 CatLog.d(this, "language: " + language);
1420 // Each language code is a pair of alpha-numeric characters.
1421 // Each alpha-numeric character shall be coded on one byte
1422 // using the SMS default 7-bit coded alphabet
1423 addedInfo = GsmAlphabet.stringToGsm8BitPacked(language);
1424 sendSetUpEventResponse(event, addedInfo, slotId);
1425 break;
1426 default:
1427 break;
1428 }
1429 } else {
1430 CatLog.e(this, " Event does not exist in the EventList");
1431 }
1432 } else {
1433 CatLog.e(this, "SetupEventList is not received. Ignoring the event: " + event);
1434 }
1435 }
1436
1437 private void removeSetUpEvent(int event, int slotId) {
1438 CatLog.d(this, "Remove Event :" + event);
1439
1440 if (mStkContext[slotId].mSetupEventListSettings != null) {
1441 /*
1442 * Make new Eventlist without the event
1443 */
1444 for (int i = 0; i < mStkContext[slotId].mSetupEventListSettings.eventList.length; i++) {
1445 if (event == mStkContext[slotId].mSetupEventListSettings.eventList[i]) {
1446 mStkContext[slotId].mSetupEventListSettings.eventList[i] = INVALID_SETUP_EVENT;
1447 break;
1448 }
1449 }
1450 }
1451 }
1452
1453 private void launchEventMessage(int slotId) {
1454 launchEventMessage(slotId, mStkContext[slotId].mCurrentCmd.geTextMessage());
1455 }
1456
Wink Savillee68857d2014-10-17 15:23:05 -07001457 private void launchEventMessage(int slotId, TextMessage msg) {
1458 if (msg == null || (msg.text != null && msg.text.length() == 0)) {
1459 CatLog.d(LOG_TAG, "launchEventMessage return");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001460 return;
1461 }
Wink Savillee68857d2014-10-17 15:23:05 -07001462
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001463 Toast toast = new Toast(mContext.getApplicationContext());
1464 LayoutInflater inflate = (LayoutInflater) mContext
1465 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
1466 View v = inflate.inflate(R.layout.stk_event_msg, null);
1467 TextView tv = (TextView) v
1468 .findViewById(com.android.internal.R.id.message);
1469 ImageView iv = (ImageView) v
1470 .findViewById(com.android.internal.R.id.icon);
1471 if (msg.icon != null) {
1472 iv.setImageBitmap(msg.icon);
1473 } else {
1474 iv.setVisibility(View.GONE);
1475 }
1476 if (!msg.iconSelfExplanatory) {
1477 tv.setText(msg.text);
1478 }
1479
1480 toast.setView(v);
1481 toast.setDuration(Toast.LENGTH_LONG);
1482 toast.setGravity(Gravity.BOTTOM, 0, 0);
1483 toast.show();
1484 }
1485
Wink Savillee68857d2014-10-17 15:23:05 -07001486 private void launchConfirmationDialog(TextMessage msg, int slotId) {
1487 msg.title = mStkContext[slotId].lastSelectedItem;
1488 Intent newIntent = new Intent();
1489 String targetActivity = STK_DIALOG_ACTIVITY_NAME;
1490 String uriString = STK_DIALOG_URI + System.currentTimeMillis();
1491 //Set unique URI to create a new instance of activity for different slotId.
1492 Uri uriData = Uri.parse(uriString);
1493
1494 if (newIntent != null) {
1495 newIntent.setClassName(this, targetActivity);
1496 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1497 | Intent.FLAG_ACTIVITY_NO_HISTORY
1498 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
1499 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1500 newIntent.putExtra("TEXT", msg);
1501 newIntent.putExtra(SLOT_ID, slotId);
1502 newIntent.setData(uriData);
1503 startActivity(newIntent);
1504 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001505 }
1506
1507 private void launchBrowser(BrowserSettings settings) {
1508 if (settings == null) {
1509 return;
1510 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001511
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001512 Intent intent = null;
1513 Uri data = null;
David Brown7c03cfe2011-10-20 15:36:12 -07001514
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001515 if (settings.url != null) {
Wink Savillee68857d2014-10-17 15:23:05 -07001516 CatLog.d(LOG_TAG, "settings.url = " + settings.url);
dujin.cha2a0eb2a2011-11-11 15:03:57 +09001517 if ((settings.url.startsWith("http://") || (settings.url.startsWith("https://")))) {
dujin.cha486c1d02011-11-02 22:14:25 +09001518 data = Uri.parse(settings.url);
1519 } else {
1520 String modifiedUrl = "http://" + settings.url;
Wink Savillee68857d2014-10-17 15:23:05 -07001521 CatLog.d(LOG_TAG, "modifiedUrl = " + modifiedUrl);
dujin.cha486c1d02011-11-02 22:14:25 +09001522 data = Uri.parse(modifiedUrl);
1523 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001524 }
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001525 if (data != null) {
1526 intent = new Intent(Intent.ACTION_VIEW);
1527 intent.setData(data);
1528 } else {
1529 // if the command did not contain a URL,
1530 // launch the browser to the default homepage.
Wink Savillee68857d2014-10-17 15:23:05 -07001531 CatLog.d(LOG_TAG, "launch browser with default URL ");
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001532 intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN,
1533 Intent.CATEGORY_APP_BROWSER);
1534 }
David Brown7c03cfe2011-10-20 15:36:12 -07001535
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001536 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1537 switch (settings.mode) {
1538 case USE_EXISTING_BROWSER:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001539 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1540 break;
1541 case LAUNCH_NEW_BROWSER:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001542 intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
1543 break;
1544 case LAUNCH_IF_NOT_ALREADY_LAUNCHED:
1545 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1546 break;
1547 }
1548 // start browser activity
1549 startActivity(intent);
1550 // a small delay, let the browser start, before processing the next command.
Wink Saville79085fc2009-06-09 10:27:23 -07001551 // this is good for scenarios where a related DISPLAY TEXT command is
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001552 // followed immediately.
1553 try {
1554 Thread.sleep(10000);
1555 } catch (InterruptedException e) {}
1556 }
1557
Wink Savillee68857d2014-10-17 15:23:05 -07001558 private void launchIdleText(int slotId) {
Preeti Ahuja95919342013-10-01 18:18:55 -07001559 TextMessage msg = mStkContext[slotId].mIdleModeTextCmd.geTextMessage();
dujin.cha2a0eb2a2011-11-11 15:03:57 +09001560
Preeti Ahuja95919342013-10-01 18:18:55 -07001561 if (msg == null || msg.text ==null) {
1562 CatLog.d(LOG_TAG, msg == null ? "mCurrent.getTextMessage is NULL"
1563 : "mCurrent.getTextMessage.text is NULL");
Wink Savillee68857d2014-10-17 15:23:05 -07001564 mNotificationManager.cancel(getNotificationId(slotId));
Wink Saville046db4b2011-11-01 20:42:54 -07001565 return;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001566 } else {
Preeti Ahuja95919342013-10-01 18:18:55 -07001567 CatLog.d(LOG_TAG, "launchIdleText - text[" + msg.text
1568 + "] iconSelfExplanatory[" + msg.iconSelfExplanatory
1569 + "] icon[" + msg.icon + "], sim id: " + slotId);
Wink Savillee68857d2014-10-17 15:23:05 -07001570 CatLog.d(LOG_TAG, "Add IdleMode text");
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001571 PendingIntent pendingIntent = PendingIntent.getService(mContext, 0,
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001572 new Intent(mContext, StkAppService.class), 0);
1573
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001574 final Notification.Builder notificationBuilder = new Notification.Builder(
1575 StkAppService.this);
Wink Savillee68857d2014-10-17 15:23:05 -07001576 if (mStkContext[slotId].mMainCmd != null &&
1577 mStkContext[slotId].mMainCmd.getMenu() != null) {
1578 notificationBuilder.setContentTitle(mStkContext[slotId].mMainCmd.getMenu().title);
Christopher Posselwhite2ad2ab72013-05-27 07:51:06 +02001579 } else {
1580 notificationBuilder.setContentTitle("");
1581 }
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001582 notificationBuilder
1583 .setSmallIcon(com.android.internal.R.drawable.stat_notify_sim_toolkit);
1584 notificationBuilder.setContentIntent(pendingIntent);
1585 notificationBuilder.setOngoing(true);
1586 // Set text and icon for the status bar and notification body.
1587 if (!msg.iconSelfExplanatory) {
1588 notificationBuilder.setContentText(msg.text);
Christopher Posselwhite2ad2ab72013-05-27 07:51:06 +02001589 notificationBuilder.setTicker(msg.text);
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001590 }
1591 if (msg.icon != null) {
1592 notificationBuilder.setLargeIcon(msg.icon);
1593 } else {
1594 Bitmap bitmapIcon = BitmapFactory.decodeResource(StkAppService.this
1595 .getResources().getSystem(),
1596 com.android.internal.R.drawable.stat_notify_sim_toolkit);
1597 notificationBuilder.setLargeIcon(bitmapIcon);
1598 }
Selim Cinek62eb3fe2014-08-27 17:52:23 +02001599 notificationBuilder.setColor(mContext.getResources().getColor(
1600 com.android.internal.R.color.system_notification_accent_color));
Wink Savillee68857d2014-10-17 15:23:05 -07001601 mNotificationManager.notify(getNotificationId(slotId), notificationBuilder.build());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001602 }
1603 }
1604
Wink Savillee68857d2014-10-17 15:23:05 -07001605 private void launchToneDialog(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001606 Intent newIntent = new Intent(this, ToneDialog.class);
Wink Savillee68857d2014-10-17 15:23:05 -07001607 String uriString = STK_TONE_URI + slotId;
1608 Uri uriData = Uri.parse(uriString);
1609 //Set unique URI to create a new instance of activity for different slotId.
1610 CatLog.d(LOG_TAG, "launchToneDialog, slotId: " + slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001611 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1612 | Intent.FLAG_ACTIVITY_NO_HISTORY
1613 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
Wink Savillee68857d2014-10-17 15:23:05 -07001614 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1615 newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
1616 newIntent.putExtra("TONE", mStkContext[slotId].mCurrentCmd.getToneSettings());
1617 newIntent.putExtra(SLOT_ID, slotId);
1618 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001619 startActivity(newIntent);
1620 }
1621
Wink Savillee68857d2014-10-17 15:23:05 -07001622 private void launchOpenChannelDialog(int slotId) {
1623 TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001624 if (msg == null) {
Wink Savillee68857d2014-10-17 15:23:05 -07001625 CatLog.d(LOG_TAG, "msg is null, return here");
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001626 return;
1627 }
1628
1629 msg.title = getResources().getString(R.string.stk_dialog_title);
1630 if (msg.text == null) {
1631 msg.text = getResources().getString(R.string.default_open_channel_msg);
1632 }
1633
1634 final AlertDialog dialog = new AlertDialog.Builder(mContext)
1635 .setIconAttribute(android.R.attr.alertDialogIcon)
1636 .setTitle(msg.title)
1637 .setMessage(msg.text)
1638 .setCancelable(false)
1639 .setPositiveButton(getResources().getString(R.string.stk_dialog_accept),
1640 new DialogInterface.OnClickListener() {
1641 public void onClick(DialogInterface dialog, int which) {
1642 Bundle args = new Bundle();
1643 args.putInt(RES_ID, RES_ID_CHOICE);
1644 args.putInt(CHOICE, YES);
1645 Message message = mServiceHandler.obtainMessage();
1646 message.arg1 = OP_RESPONSE;
1647 message.obj = args;
1648 mServiceHandler.sendMessage(message);
1649 }
1650 })
1651 .setNegativeButton(getResources().getString(R.string.stk_dialog_reject),
1652 new DialogInterface.OnClickListener() {
1653 public void onClick(DialogInterface dialog, int which) {
1654 Bundle args = new Bundle();
1655 args.putInt(RES_ID, RES_ID_CHOICE);
1656 args.putInt(CHOICE, NO);
1657 Message message = mServiceHandler.obtainMessage();
1658 message.arg1 = OP_RESPONSE;
1659 message.obj = args;
1660 mServiceHandler.sendMessage(message);
1661 }
1662 })
1663 .create();
1664
1665 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1666 if (!mContext.getResources().getBoolean(
1667 com.android.internal.R.bool.config_sf_slowBlur)) {
1668 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
1669 }
1670
1671 dialog.show();
1672 }
1673
Wink Savillee68857d2014-10-17 15:23:05 -07001674 private void launchTransientEventMessage(int slotId) {
1675 TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001676 if (msg == null) {
Wink Savillee68857d2014-10-17 15:23:05 -07001677 CatLog.d(LOG_TAG, "msg is null, return here");
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001678 return;
1679 }
1680
1681 msg.title = getResources().getString(R.string.stk_dialog_title);
1682
1683 final AlertDialog dialog = new AlertDialog.Builder(mContext)
1684 .setIconAttribute(android.R.attr.alertDialogIcon)
1685 .setTitle(msg.title)
1686 .setMessage(msg.text)
1687 .setCancelable(false)
1688 .setPositiveButton(getResources().getString(android.R.string.ok),
1689 new DialogInterface.OnClickListener() {
1690 public void onClick(DialogInterface dialog, int which) {
1691 }
1692 })
1693 .create();
1694
1695 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1696 if (!mContext.getResources().getBoolean(
1697 com.android.internal.R.bool.config_sf_slowBlur)) {
1698 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
1699 }
1700
1701 dialog.show();
1702 }
1703
Wink Savillee68857d2014-10-17 15:23:05 -07001704 private int getNotificationId(int slotId) {
1705 int notifyId = STK_NOTIFICATION_ID;
1706 if (slotId >= 0 && slotId < mSimCount) {
1707 notifyId += slotId;
1708 } else {
1709 CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
1710 }
1711 CatLog.d(LOG_TAG, "getNotificationId, slotId: " + slotId + ", notifyId: " + notifyId);
1712 return notifyId;
1713 }
1714
1715 private String getItemName(int itemId, int slotId) {
1716 Menu menu = mStkContext[slotId].mCurrentCmd.getMenu();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001717 if (menu == null) {
1718 return null;
1719 }
1720 for (Item item : menu.items) {
1721 if (item.id == itemId) {
1722 return item.text;
1723 }
1724 }
1725 return null;
1726 }
1727
Wink Savillee68857d2014-10-17 15:23:05 -07001728 private boolean removeMenu(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001729 try {
Wink Savillee68857d2014-10-17 15:23:05 -07001730 if (mStkContext[slotId].mCurrentMenu.items.size() == 1 &&
1731 mStkContext[slotId].mCurrentMenu.items.get(0) == null) {
1732 mStkContext[slotId].mSetupMenuState = STATE_NOT_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001733 return true;
1734 }
1735 } catch (NullPointerException e) {
Wink Savillee68857d2014-10-17 15:23:05 -07001736 CatLog.d(LOG_TAG, "Unable to get Menu's items size");
1737 mStkContext[slotId].mSetupMenuState = STATE_NOT_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001738 return true;
1739 }
Wink Savillee68857d2014-10-17 15:23:05 -07001740 mStkContext[slotId].mSetupMenuState = STATE_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001741 return false;
1742 }
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +05301743
Wink Savillee68857d2014-10-17 15:23:05 -07001744 StkContext getStkContext(int slotId) {
1745 if (slotId >= 0 && slotId < mSimCount) {
1746 return mStkContext[slotId];
1747 } else {
1748 CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
1749 return null;
1750 }
1751 }
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +05301752
1753 private void handleAlphaNotify(Bundle args) {
1754 String alphaString = args.getString(AppInterface.ALPHA_STRING);
1755
1756 CatLog.d(this, "Alpha string received from card: " + alphaString);
1757 Toast toast = Toast.makeText(sInstance, alphaString, Toast.LENGTH_LONG);
1758 toast.setGravity(Gravity.TOP, 0, 0);
1759 toast.show();
1760 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001761}