blob: 0f4107c417141f76b2847a43a9654683e0c10aa8 [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 Ahuja560be362014-11-25 19:38:24 -080042import android.os.PowerManager;
Preeti Ahuja95919342013-10-01 18:18:55 -070043import android.provider.Settings;
Wink Saville56469d52009-04-02 01:37:03 -070044import android.telephony.TelephonyManager;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080045import android.view.Gravity;
46import android.view.LayoutInflater;
47import android.view.View;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -050048import android.view.Window;
49import android.view.WindowManager;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080050import android.widget.ImageView;
51import android.widget.RemoteViews;
52import android.widget.TextView;
53import android.widget.Toast;
Wink Savillee68857d2014-10-17 15:23:05 -070054import android.content.BroadcastReceiver;
55import android.content.IntentFilter;
56import android.content.pm.ApplicationInfo;
57import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080058
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070059import com.android.internal.telephony.cat.AppInterface;
Preeti Ahuja95919342013-10-01 18:18:55 -070060import com.android.internal.telephony.cat.LaunchBrowserMode;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070061import com.android.internal.telephony.cat.Menu;
62import com.android.internal.telephony.cat.Item;
Pierre Fröjd97503262010-11-08 13:59:36 +010063import com.android.internal.telephony.cat.Input;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070064import com.android.internal.telephony.cat.ResultCode;
65import com.android.internal.telephony.cat.CatCmdMessage;
66import com.android.internal.telephony.cat.CatCmdMessage.BrowserSettings;
Preeti Ahuja95919342013-10-01 18:18:55 -070067import com.android.internal.telephony.cat.CatCmdMessage.SetupEventListSettings;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070068import com.android.internal.telephony.cat.CatLog;
69import com.android.internal.telephony.cat.CatResponseMessage;
70import com.android.internal.telephony.cat.TextMessage;
Wink Saville94e982b2014-07-11 07:38:14 -070071import com.android.internal.telephony.uicc.IccRefreshResponse;
72import com.android.internal.telephony.uicc.IccCardStatus.CardState;
Wink Savillee68857d2014-10-17 15:23:05 -070073import com.android.internal.telephony.PhoneConstants;
74import com.android.internal.telephony.TelephonyIntents;
75import com.android.internal.telephony.IccCardConstants;
76import com.android.internal.telephony.uicc.UiccController;
Preeti Ahuja95919342013-10-01 18:18:55 -070077import com.android.internal.telephony.GsmAlphabet;
Legler Wuaeefef52014-10-27 00:57:18 +080078import com.android.internal.telephony.cat.CatService;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080079
80import java.util.LinkedList;
Wink Savillee68857d2014-10-17 15:23:05 -070081import java.lang.System;
82import java.util.List;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080083
Preeti Ahuja95919342013-10-01 18:18:55 -070084import static com.android.internal.telephony.cat.CatCmdMessage.
Preeti Ahuja560be362014-11-25 19:38:24 -080085 SetupEventListConstants.IDLE_SCREEN_AVAILABLE_EVENT;
86import static com.android.internal.telephony.cat.CatCmdMessage.
Preeti Ahuja95919342013-10-01 18:18:55 -070087 SetupEventListConstants.LANGUAGE_SELECTION_EVENT;
88
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080089/**
90 * SIM toolkit application level service. Interacts with Telephopny messages,
91 * application's launch and user input from STK UI elements.
Wink Saville79085fc2009-06-09 10:27:23 -070092 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080093 */
94public class StkAppService extends Service implements Runnable {
95
96 // members
Wink Savillee68857d2014-10-17 15:23:05 -070097 protected class StkContext {
98 protected CatCmdMessage mMainCmd = null;
99 protected CatCmdMessage mCurrentCmd = null;
100 protected CatCmdMessage mCurrentMenuCmd = null;
101 protected Menu mCurrentMenu = null;
102 protected String lastSelectedItem = null;
103 protected boolean mMenuIsVisible = false;
104 protected boolean mIsInputPending = false;
105 protected boolean mIsMenuPending = false;
106 protected boolean mIsDialogPending = false;
107 protected boolean responseNeeded = true;
108 protected boolean launchBrowser = false;
109 protected BrowserSettings mBrowserSettings = null;
110 protected LinkedList<DelayedCmd> mCmdsQ = null;
111 protected boolean mCmdInProgress = false;
112 protected int mStkServiceState = STATE_UNKNOWN;
113 protected int mSetupMenuState = STATE_UNKNOWN;
114 protected int mMenuState = StkMenuActivity.STATE_INIT;
115 protected int mOpCode = -1;
116 private Activity mActivityInstance = null;
117 private Activity mDialogInstance = null;
118 private Activity mMainActivityInstance = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700119 private int mSlotId = 0;
Preeti Ahuja95919342013-10-01 18:18:55 -0700120 private SetupEventListSettings mSetupEventListSettings = null;
121 private boolean mClearSelectItem = false;
122 private boolean mDisplayTextDlgIsVisibile = false;
123 private CatCmdMessage mCurrentSetupEventCmd = null;
Preeti Ahuja560be362014-11-25 19:38:24 -0800124 private CatCmdMessage mIdleModeTextCmd = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700125 final synchronized void setPendingActivityInstance(Activity act) {
126 CatLog.d(this, "setPendingActivityInstance act : " + mSlotId + ", " + act);
127 callSetActivityInstMsg(OP_SET_ACT_INST, mSlotId, act);
128 }
129 final synchronized Activity getPendingActivityInstance() {
130 CatLog.d(this, "getPendingActivityInstance act : " + mSlotId + ", " +
131 mActivityInstance);
132 return mActivityInstance;
133 }
134 final synchronized void setPendingDialogInstance(Activity act) {
135 CatLog.d(this, "setPendingDialogInstance act : " + mSlotId + ", " + act);
136 callSetActivityInstMsg(OP_SET_DAL_INST, mSlotId, act);
137 }
138 final synchronized Activity getPendingDialogInstance() {
139 CatLog.d(this, "getPendingDialogInstance act : " + mSlotId + ", " +
140 mDialogInstance);
141 return mDialogInstance;
142 }
143 final synchronized void setMainActivityInstance(Activity act) {
144 CatLog.d(this, "setMainActivityInstance act : " + mSlotId + ", " + act);
145 callSetActivityInstMsg(OP_SET_MAINACT_INST, mSlotId, act);
146 }
147 final synchronized Activity getMainActivityInstance() {
148 CatLog.d(this, "getMainActivityInstance act : " + mSlotId + ", " +
149 mMainActivityInstance);
150 return mMainActivityInstance;
151 }
152 }
153
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800154 private volatile Looper mServiceLooper;
155 private volatile ServiceHandler mServiceHandler;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800156 private Context mContext = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800157 private NotificationManager mNotificationManager = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800158 static StkAppService sInstance = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700159 private AppInterface[] mStkService = null;
160 private StkContext[] mStkContext = null;
161 private int mSimCount = 0;
Preeti Ahuja560be362014-11-25 19:38:24 -0800162 private PowerManager mPowerManager = null;
163 private StkCmdReceiver mStkCmdReceiver = null;
Preeti Ahuja95919342013-10-01 18:18:55 -0700164
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800165 // Used for setting FLAG_ACTIVITY_NO_USER_ACTION when
166 // creating an intent.
167 private enum InitiatedByUserAction {
168 yes, // The action was started via a user initiated action
169 unknown, // Not known for sure if user initated the action
170 }
171
172 // constants
173 static final String OPCODE = "op";
174 static final String CMD_MSG = "cmd message";
175 static final String RES_ID = "response id";
176 static final String MENU_SELECTION = "menu selection";
177 static final String INPUT = "input";
178 static final String HELP = "help";
179 static final String CONFIRMATION = "confirm";
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500180 static final String CHOICE = "choice";
Wink Savillee68857d2014-10-17 15:23:05 -0700181 static final String SLOT_ID = "SLOT_ID";
182 static final String STK_CMD = "STK CMD";
183 static final String STK_DIALOG_URI = "stk://com.android.stk/dialog/";
184 static final String STK_MENU_URI = "stk://com.android.stk/menu/";
185 static final String STK_INPUT_URI = "stk://com.android.stk/input/";
186 static final String STK_TONE_URI = "stk://com.android.stk/tone/";
Preeti Ahuja95919342013-10-01 18:18:55 -0700187
188 // These below constants are used for SETUP_EVENT_LIST
189 static final String SETUP_EVENT_TYPE = "event";
190 static final String SETUP_EVENT_CAUSE = "cause";
191
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800192 // operations ids for different service functionality.
193 static final int OP_CMD = 1;
194 static final int OP_RESPONSE = 2;
195 static final int OP_LAUNCH_APP = 3;
196 static final int OP_END_SESSION = 4;
197 static final int OP_BOOT_COMPLETED = 5;
198 private static final int OP_DELAYED_MSG = 6;
Wink Saville94e982b2014-07-11 07:38:14 -0700199 static final int OP_CARD_STATUS_CHANGED = 7;
Wink Savillee68857d2014-10-17 15:23:05 -0700200 static final int OP_SET_ACT_INST = 8;
201 static final int OP_SET_DAL_INST = 9;
202 static final int OP_SET_MAINACT_INST = 10;
Preeti Ahujab3d0e612014-11-20 13:29:25 -0800203 static final int OP_LOCALE_CHANGED = 11;
204 static final int OP_ALPHA_NOTIFY = 12;
Preeti Ahuja560be362014-11-25 19:38:24 -0800205 static final int OP_IDLE_SCREEN = 13;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800206
Preeti Ahuja95919342013-10-01 18:18:55 -0700207 //Invalid SetupEvent
208 static final int INVALID_SETUP_EVENT = 0xFF;
209
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800210 // Response ids
211 static final int RES_ID_MENU_SELECTION = 11;
212 static final int RES_ID_INPUT = 12;
213 static final int RES_ID_CONFIRM = 13;
214 static final int RES_ID_DONE = 14;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500215 static final int RES_ID_CHOICE = 15;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800216
217 static final int RES_ID_TIMEOUT = 20;
218 static final int RES_ID_BACKWARD = 21;
219 static final int RES_ID_END_SESSION = 22;
220 static final int RES_ID_EXIT = 23;
221
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500222 static final int YES = 1;
223 static final int NO = 0;
224
Wink Savillee68857d2014-10-17 15:23:05 -0700225 static final int STATE_UNKNOWN = -1;
226 static final int STATE_NOT_EXIST = 0;
227 static final int STATE_EXIST = 1;
Wink Saville79085fc2009-06-09 10:27:23 -0700228
Wink Savillee68857d2014-10-17 15:23:05 -0700229 private static final String PACKAGE_NAME = "com.android.stk";
230 private static final String STK_MENU_ACTIVITY_NAME = PACKAGE_NAME + ".StkMenuActivity";
231 private static final String STK_INPUT_ACTIVITY_NAME = PACKAGE_NAME + ".StkInputActivity";
232 private static final String STK_DIALOG_ACTIVITY_NAME = PACKAGE_NAME + ".StkDialogActivity";
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800233 // Notification id used to display Idle Mode text in NotificationManager.
234 private static final int STK_NOTIFICATION_ID = 333;
Wink Savillee68857d2014-10-17 15:23:05 -0700235 private static final String LOG_TAG = new Object(){}.getClass().getEnclosingClass().getName();
Wink Saville79085fc2009-06-09 10:27:23 -0700236
237 // Inner class used for queuing telephony messages (proactive commands,
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800238 // session end) while the service is busy processing a previous message.
239 private class DelayedCmd {
240 // members
241 int id;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700242 CatCmdMessage msg;
Wink Savillee68857d2014-10-17 15:23:05 -0700243 int slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800244
Wink Savillee68857d2014-10-17 15:23:05 -0700245 DelayedCmd(int id, CatCmdMessage msg, int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800246 this.id = id;
247 this.msg = msg;
Wink Savillee68857d2014-10-17 15:23:05 -0700248 this.slotId = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800249 }
250 }
251
252 @Override
253 public void onCreate() {
Wink Savillee68857d2014-10-17 15:23:05 -0700254 CatLog.d(LOG_TAG, "onCreate()+");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800255 // Initialize members
Wink Savillee68857d2014-10-17 15:23:05 -0700256 int i = 0;
257 mContext = getBaseContext();
258 mSimCount = TelephonyManager.from(mContext).getSimCount();
259 CatLog.d(LOG_TAG, "simCount: " + mSimCount);
260 mStkService = new AppInterface[mSimCount];
261 mStkContext = new StkContext[mSimCount];
Preeti Ahuja560be362014-11-25 19:38:24 -0800262 mPowerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
263 mStkCmdReceiver = new StkCmdReceiver();
264 registerReceiver(mStkCmdReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
Wink Savillee68857d2014-10-17 15:23:05 -0700265 for (i = 0; i < mSimCount; i++) {
266 CatLog.d(LOG_TAG, "slotId: " + i);
Legler Wuaeefef52014-10-27 00:57:18 +0800267 mStkService[i] = CatService.getInstance(i);
Wink Savillee68857d2014-10-17 15:23:05 -0700268 mStkContext[i] = new StkContext();
269 mStkContext[i].mSlotId = i;
270 mStkContext[i].mCmdsQ = new LinkedList<DelayedCmd>();
271 }
272
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800273 Thread serviceThread = new Thread(null, this, "Stk App Service");
274 serviceThread.start();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800275 mNotificationManager = (NotificationManager) mContext
276 .getSystemService(Context.NOTIFICATION_SERVICE);
277 sInstance = this;
278 }
279
280 @Override
281 public void onStart(Intent intent, int startId) {
Wink Savillee68857d2014-10-17 15:23:05 -0700282 if (intent == null) {
283 CatLog.d(LOG_TAG, "StkAppService onStart intent is null so return");
Banavathu, Srinivas Naik87cda962012-07-17 15:32:44 +0530284 return;
285 }
286
Wink Savillee68857d2014-10-17 15:23:05 -0700287 Bundle args = intent.getExtras();
288 if (args == null) {
289 CatLog.d(LOG_TAG, "StkAppService onStart args is null so return");
290 return;
291 }
292
293 int op = args.getInt(OPCODE);
294 int slotId = 0;
295 int i = 0;
296 if (op != OP_BOOT_COMPLETED) {
297 slotId = args.getInt(SLOT_ID);
298 }
Cuihtlauac ALVARADObde7f032015-05-29 16:25:12 +0200299 CatLog.d(LOG_TAG, "onStart sim id: " + slotId + ", op: " + op + ", *****");
Wink Savillee68857d2014-10-17 15:23:05 -0700300 if ((slotId >= 0 && slotId < mSimCount) && mStkService[slotId] == null) {
Legler Wuaeefef52014-10-27 00:57:18 +0800301 mStkService[slotId] = CatService.getInstance(slotId);
Wink Savillee68857d2014-10-17 15:23:05 -0700302 if (mStkService[slotId] == null) {
303 CatLog.d(LOG_TAG, "mStkService is: " + mStkContext[slotId].mStkServiceState);
304 mStkContext[slotId].mStkServiceState = STATE_NOT_EXIST;
305 //Check other StkService state.
306 //If all StkServices are not available, stop itself and uninstall apk.
307 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
308 if (i != slotId
309 && (mStkContext[i].mStkServiceState == STATE_UNKNOWN
310 || mStkContext[i].mStkServiceState == STATE_EXIST)) {
311 break;
312 }
313 }
314 } else {
315 mStkContext[slotId].mStkServiceState = STATE_EXIST;
316 }
317 if (i == mSimCount) {
318 stopSelf();
319 StkAppInstaller.unInstall(mContext);
320 return;
321 }
322 }
323
Banavathu, Srinivas Naik87cda962012-07-17 15:32:44 +0530324 waitForLooper();
John Wang62acae42009-10-08 11:20:23 -0700325
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800326 Message msg = mServiceHandler.obtainMessage();
Wink Savillee68857d2014-10-17 15:23:05 -0700327 msg.arg1 = op;
328 msg.arg2 = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800329 switch(msg.arg1) {
330 case OP_CMD:
331 msg.obj = args.getParcelable(CMD_MSG);
332 break;
333 case OP_RESPONSE:
Wink Saville94e982b2014-07-11 07:38:14 -0700334 case OP_CARD_STATUS_CHANGED:
Preeti Ahuja95919342013-10-01 18:18:55 -0700335 case OP_LOCALE_CHANGED:
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +0530336 case OP_ALPHA_NOTIFY:
Preeti Ahuja560be362014-11-25 19:38:24 -0800337 case OP_IDLE_SCREEN:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800338 msg.obj = args;
339 /* falls through */
340 case OP_LAUNCH_APP:
341 case OP_END_SESSION:
342 case OP_BOOT_COMPLETED:
343 break;
344 default:
345 return;
346 }
347 mServiceHandler.sendMessage(msg);
348 }
349
350 @Override
351 public void onDestroy() {
Wink Savillee68857d2014-10-17 15:23:05 -0700352 CatLog.d(LOG_TAG, "onDestroy()");
Preeti Ahuja560be362014-11-25 19:38:24 -0800353 if (mStkCmdReceiver != null) {
354 unregisterReceiver(mStkCmdReceiver);
355 mStkCmdReceiver = null;
356 }
357 mPowerManager = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800358 waitForLooper();
359 mServiceLooper.quit();
360 }
361
362 @Override
363 public IBinder onBind(Intent intent) {
364 return null;
365 }
366
367 public void run() {
368 Looper.prepare();
369
370 mServiceLooper = Looper.myLooper();
371 mServiceHandler = new ServiceHandler();
372
373 Looper.loop();
374 }
375
376 /*
377 * Package api used by StkMenuActivity to indicate if its on the foreground.
378 */
Wink Savillee68857d2014-10-17 15:23:05 -0700379 void indicateMenuVisibility(boolean visibility, int slotId) {
380 if (slotId >= 0 && slotId < mSimCount) {
381 mStkContext[slotId].mMenuIsVisible = visibility;
382 }
383 }
384
Preeti Ahuja95919342013-10-01 18:18:55 -0700385 /*
386 * Package api used by StkDialogActivity to indicate if its on the foreground.
387 */
388 void setDisplayTextDlgVisibility(boolean visibility, int slotId) {
389 if (slotId >= 0 && slotId < mSimCount) {
390 mStkContext[slotId].mDisplayTextDlgIsVisibile = visibility;
391 }
392 }
393
Wink Savillee68857d2014-10-17 15:23:05 -0700394 boolean isInputPending(int slotId) {
395 if (slotId >= 0 && slotId < mSimCount) {
396 CatLog.d(LOG_TAG, "isInputFinishBySrv: " + mStkContext[slotId].mIsInputPending);
397 return mStkContext[slotId].mIsInputPending;
398 }
399 return false;
400 }
401
402 boolean isMenuPending(int slotId) {
403 if (slotId >= 0 && slotId < mSimCount) {
404 CatLog.d(LOG_TAG, "isMenuPending: " + mStkContext[slotId].mIsMenuPending);
405 return mStkContext[slotId].mIsMenuPending;
406 }
407 return false;
408 }
409
410 boolean isDialogPending(int slotId) {
411 if (slotId >= 0 && slotId < mSimCount) {
412 CatLog.d(LOG_TAG, "isDialogPending: " + mStkContext[slotId].mIsDialogPending);
413 return mStkContext[slotId].mIsDialogPending;
414 }
415 return false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800416 }
417
418 /*
419 * Package api used by StkMenuActivity to get its Menu parameter.
420 */
Wink Savillee68857d2014-10-17 15:23:05 -0700421 Menu getMenu(int slotId) {
422 CatLog.d(LOG_TAG, "StkAppService, getMenu, sim id: " + slotId);
423 if (slotId >=0 && slotId < mSimCount) {
424 return mStkContext[slotId].mCurrentMenu;
425 } else {
426 return null;
427 }
428 }
429
430 /*
431 * Package api used by StkMenuActivity to get its Main Menu parameter.
432 */
433 Menu getMainMenu(int slotId) {
434 CatLog.d(LOG_TAG, "StkAppService, getMainMenu, sim id: " + slotId);
w30234a08cffe2015-02-04 15:13:25 -0800435 if (slotId >=0 && slotId < mSimCount && (mStkContext[slotId].mMainCmd != null)) {
Wink Savillee68857d2014-10-17 15:23:05 -0700436 return mStkContext[slotId].mMainCmd.getMenu();
437 } else {
438 return null;
439 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800440 }
441
442 /*
443 * Package api used by UI Activities and Dialogs to communicate directly
444 * with the service to deliver state information and parameters.
445 */
446 static StkAppService getInstance() {
447 return sInstance;
448 }
449
450 private void waitForLooper() {
451 while (mServiceHandler == null) {
452 synchronized (this) {
453 try {
454 wait(100);
455 } catch (InterruptedException e) {
456 }
457 }
458 }
459 }
460
461 private final class ServiceHandler extends Handler {
462 @Override
463 public void handleMessage(Message msg) {
Wink Savillee68857d2014-10-17 15:23:05 -0700464 if(null == msg) {
465 CatLog.d(LOG_TAG, "ServiceHandler handleMessage msg is null");
466 return;
467 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800468 int opcode = msg.arg1;
Wink Savillee68857d2014-10-17 15:23:05 -0700469 int slotId = msg.arg2;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800470
Wink Savillee68857d2014-10-17 15:23:05 -0700471 CatLog.d(LOG_TAG, "handleMessage opcode[" + opcode + "], sim id[" + slotId + "]");
472 if (opcode == OP_CMD && msg.obj != null &&
473 ((CatCmdMessage)msg.obj).getCmdType()!= null) {
474 CatLog.d(LOG_TAG, "cmdName[" + ((CatCmdMessage)msg.obj).getCmdType().name() + "]");
475 }
476 mStkContext[slotId].mOpCode = opcode;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800477 switch (opcode) {
478 case OP_LAUNCH_APP:
Wink Savillee68857d2014-10-17 15:23:05 -0700479 if (mStkContext[slotId].mMainCmd == null) {
480 CatLog.d(LOG_TAG, "mMainCmd is null");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800481 // nothing todo when no SET UP MENU command didn't arrive.
482 return;
483 }
Wink Savillee68857d2014-10-17 15:23:05 -0700484 CatLog.d(LOG_TAG, "handleMessage OP_LAUNCH_APP - mCmdInProgress[" +
485 mStkContext[slotId].mCmdInProgress + "]");
486
487 //If there is a pending activity for the slot id,
488 //just finish it and create a new one to handle the pending command.
489 cleanUpInstanceStackBySlot(slotId);
490
Wink Savillee68857d2014-10-17 15:23:05 -0700491 CatLog.d(LOG_TAG, "Current cmd type: " +
492 mStkContext[slotId].mCurrentCmd.getCmdType());
493 //Restore the last command from stack by slot id.
494 restoreInstanceFromStackBySlot(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800495 break;
496 case OP_CMD:
Wink Savillee68857d2014-10-17 15:23:05 -0700497 CatLog.d(LOG_TAG, "[OP_CMD]");
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700498 CatCmdMessage cmdMsg = (CatCmdMessage) msg.obj;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800499 // There are two types of commands:
500 // 1. Interactive - user's response is required.
501 // 2. Informative - display a message, no interaction with the user.
502 //
Wink Saville79085fc2009-06-09 10:27:23 -0700503 // Informative commands can be handled immediately without any delay.
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800504 // Interactive commands can't override each other. So if a command
505 // is already in progress, we need to queue the next command until
506 // the user has responded or a timeout expired.
507 if (!isCmdInteractive(cmdMsg)) {
Wink Savillee68857d2014-10-17 15:23:05 -0700508 handleCmd(cmdMsg, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800509 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700510 if (!mStkContext[slotId].mCmdInProgress) {
511 mStkContext[slotId].mCmdInProgress = true;
512 handleCmd((CatCmdMessage) msg.obj, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800513 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700514 CatLog.d(LOG_TAG, "[Interactive][in progress]");
515 mStkContext[slotId].mCmdsQ.addLast(new DelayedCmd(OP_CMD,
516 (CatCmdMessage) msg.obj, slotId));
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800517 }
518 }
519 break;
520 case OP_RESPONSE:
Preeti Ahuja414bc412013-06-25 19:31:49 -0700521 handleCmdResponse((Bundle) msg.obj, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800522 // call delayed commands if needed.
Wink Savillee68857d2014-10-17 15:23:05 -0700523 if (mStkContext[slotId].mCmdsQ.size() != 0) {
524 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800525 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700526 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800527 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800528 break;
529 case OP_END_SESSION:
Wink Savillee68857d2014-10-17 15:23:05 -0700530 if (!mStkContext[slotId].mCmdInProgress) {
531 mStkContext[slotId].mCmdInProgress = true;
532 handleSessionEnd(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800533 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700534 mStkContext[slotId].mCmdsQ.addLast(
535 new DelayedCmd(OP_END_SESSION, null, slotId));
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800536 }
537 break;
538 case OP_BOOT_COMPLETED:
Wink Savillee68857d2014-10-17 15:23:05 -0700539 CatLog.d(LOG_TAG, " OP_BOOT_COMPLETED");
540 int i = 0;
541 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
542 if (mStkContext[i].mMainCmd != null) {
543 break;
544 }
545 }
546 if (i == mSimCount) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800547 StkAppInstaller.unInstall(mContext);
548 }
549 break;
550 case OP_DELAYED_MSG:
Wink Savillee68857d2014-10-17 15:23:05 -0700551 handleDelayedCmd(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800552 break;
Wink Saville94e982b2014-07-11 07:38:14 -0700553 case OP_CARD_STATUS_CHANGED:
Wink Savillee68857d2014-10-17 15:23:05 -0700554 CatLog.d(LOG_TAG, "Card/Icc Status change received");
555 handleCardStatusChangeAndIccRefresh((Bundle) msg.obj, slotId);
556 break;
557 case OP_SET_ACT_INST:
558 Activity act = new Activity();
559 act = (Activity) msg.obj;
560 CatLog.d(LOG_TAG, "Set activity instance. " + act);
561 mStkContext[slotId].mActivityInstance = act;
562 break;
563 case OP_SET_DAL_INST:
564 Activity dal = new Activity();
565 CatLog.d(LOG_TAG, "Set dialog instance. " + dal);
566 dal = (Activity) msg.obj;
567 mStkContext[slotId].mDialogInstance = dal;
568 break;
569 case OP_SET_MAINACT_INST:
570 Activity mainAct = new Activity();
571 mainAct = (Activity) msg.obj;
572 CatLog.d(LOG_TAG, "Set activity instance. " + mainAct);
573 mStkContext[slotId].mMainActivityInstance = mainAct;
Wink Saville94e982b2014-07-11 07:38:14 -0700574 break;
Preeti Ahuja95919342013-10-01 18:18:55 -0700575 case OP_LOCALE_CHANGED:
576 CatLog.d(this, "Locale Changed");
577 checkForSetupEvent(LANGUAGE_SELECTION_EVENT,(Bundle) msg.obj, slotId);
578 break;
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +0530579 case OP_ALPHA_NOTIFY:
580 handleAlphaNotify((Bundle) msg.obj);
581 break;
Preeti Ahuja560be362014-11-25 19:38:24 -0800582 case OP_IDLE_SCREEN:
583 for (int slot = 0; slot < mSimCount; slot++) {
584 if (mStkContext[slot] != null) {
585 handleIdleScreen(slot);
586 }
587 }
588 break;
Wink Saville94e982b2014-07-11 07:38:14 -0700589 }
590 }
591
Wink Savillee68857d2014-10-17 15:23:05 -0700592 private void handleCardStatusChangeAndIccRefresh(Bundle args, int slotId) {
Wink Saville94e982b2014-07-11 07:38:14 -0700593 boolean cardStatus = args.getBoolean(AppInterface.CARD_STATUS);
594
Wink Savillee68857d2014-10-17 15:23:05 -0700595 CatLog.d(LOG_TAG, "CardStatus: " + cardStatus);
Wink Saville94e982b2014-07-11 07:38:14 -0700596 if (cardStatus == false) {
Wink Savillee68857d2014-10-17 15:23:05 -0700597 CatLog.d(LOG_TAG, "CARD is ABSENT");
Wink Saville94e982b2014-07-11 07:38:14 -0700598 // Uninstall STKAPP, Clear Idle text, Stop StkAppService
Wink Savillee68857d2014-10-17 15:23:05 -0700599 mNotificationManager.cancel(getNotificationId(slotId));
600 if (isAllOtherCardsAbsent(slotId)) {
601 CatLog.d(LOG_TAG, "All CARDs are ABSENT");
602 StkAppInstaller.unInstall(mContext);
603 stopSelf();
604 }
Wink Saville94e982b2014-07-11 07:38:14 -0700605 } else {
606 IccRefreshResponse state = new IccRefreshResponse();
607 state.refreshResult = args.getInt(AppInterface.REFRESH_RESULT);
608
Wink Savillee68857d2014-10-17 15:23:05 -0700609 CatLog.d(LOG_TAG, "Icc Refresh Result: "+ state.refreshResult);
Wink Saville94e982b2014-07-11 07:38:14 -0700610 if ((state.refreshResult == IccRefreshResponse.REFRESH_RESULT_INIT) ||
611 (state.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET)) {
612 // Clear Idle Text
Wink Savillee68857d2014-10-17 15:23:05 -0700613 mNotificationManager.cancel(getNotificationId(slotId));
Wink Saville94e982b2014-07-11 07:38:14 -0700614 }
615
616 if (state.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET) {
617 // Uninstall STkmenu
Wink Savillee68857d2014-10-17 15:23:05 -0700618 if (isAllOtherCardsAbsent(slotId)) {
619 StkAppInstaller.unInstall(mContext);
620 }
621 mStkContext[slotId].mCurrentMenu = null;
622 mStkContext[slotId].mMainCmd = null;
Wink Saville94e982b2014-07-11 07:38:14 -0700623 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800624 }
625 }
626 }
Wink Savillee68857d2014-10-17 15:23:05 -0700627 /*
628 * Check if all SIMs are absent except the id of slot equals "slotId".
629 */
630 private boolean isAllOtherCardsAbsent(int slotId) {
631 TelephonyManager mTm = (TelephonyManager) mContext.getSystemService(
632 Context.TELEPHONY_SERVICE);
633 int i = 0;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800634
Wink Savillee68857d2014-10-17 15:23:05 -0700635 for (i = 0; i < mSimCount; i++) {
636 if (i != slotId && mTm.hasIccCard(i)) {
637 break;
638 }
639 }
640 if (i == mSimCount) {
641 return true;
642 } else {
643 return false;
644 }
645 }
Preeti Ahuja95919342013-10-01 18:18:55 -0700646
Preeti Ahuja560be362014-11-25 19:38:24 -0800647 /*
648 * If the device is not in an interactive state, we can assume
649 * that the screen is idle.
650 */
651 private boolean isScreenIdle() {
652 return (!mPowerManager.isInteractive());
653 }
654
655 private void handleIdleScreen(int slotId) {
656
657 // If the idle screen event is present in the list need to send the
658 // response to SIM.
659 CatLog.d(this, "Need to send IDLE SCREEN Available event to SIM");
660 checkForSetupEvent(IDLE_SCREEN_AVAILABLE_EVENT, null, slotId);
661
662 if (mStkContext[slotId].mIdleModeTextCmd != null) {
663 launchIdleText(slotId);
664 }
665 }
666
667 private void sendScreenBusyResponse(int slotId) {
668 if (mStkContext[slotId].mCurrentCmd == null) {
669 return;
670 }
671 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentCmd);
672 CatLog.d(this, "SCREEN_BUSY");
673 resMsg.setResultCode(ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS);
674 mStkService[slotId].onCmdResponse(resMsg);
675 if (mStkContext[slotId].mCmdsQ.size() != 0) {
676 callDelayedMsg(slotId);
677 } else {
678 mStkContext[slotId].mCmdInProgress = false;
679 }
680 }
681
Preeti Ahuja95919342013-10-01 18:18:55 -0700682 private void sendResponse(int resId, int slotId, boolean confirm) {
683 Message msg = mServiceHandler.obtainMessage();
684 msg.arg1 = OP_RESPONSE;
685 Bundle args = new Bundle();
686 args.putInt(StkAppService.RES_ID, resId);
687 args.putInt(SLOT_ID, slotId);
688 args.putBoolean(StkAppService.CONFIRMATION, confirm);
689 msg.obj = args;
690 mServiceHandler.sendMessage(msg);
691 }
692
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700693 private boolean isCmdInteractive(CatCmdMessage cmd) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800694 switch (cmd.getCmdType()) {
695 case SEND_DTMF:
696 case SEND_SMS:
697 case SEND_SS:
698 case SEND_USSD:
699 case SET_UP_IDLE_MODE_TEXT:
700 case SET_UP_MENU:
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500701 case CLOSE_CHANNEL:
702 case RECEIVE_DATA:
703 case SEND_DATA:
Preeti Ahuja95919342013-10-01 18:18:55 -0700704 case SET_UP_EVENT_LIST:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800705 return false;
706 }
707
708 return true;
709 }
710
Wink Savillee68857d2014-10-17 15:23:05 -0700711 private void handleDelayedCmd(int slotId) {
712 CatLog.d(LOG_TAG, "handleDelayedCmd, slotId: " + slotId);
713 if (mStkContext[slotId].mCmdsQ.size() != 0) {
714 DelayedCmd cmd = mStkContext[slotId].mCmdsQ.poll();
715 if (cmd != null) {
716 CatLog.d(LOG_TAG, "handleDelayedCmd - queue size: " +
717 mStkContext[slotId].mCmdsQ.size() +
718 " id: " + cmd.id + "sim id: " + cmd.slotId);
719 switch (cmd.id) {
720 case OP_CMD:
721 handleCmd(cmd.msg, cmd.slotId);
722 break;
723 case OP_END_SESSION:
724 handleSessionEnd(cmd.slotId);
725 break;
726 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800727 }
728 }
729 }
730
Wink Savillee68857d2014-10-17 15:23:05 -0700731 private void callDelayedMsg(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800732 Message msg = mServiceHandler.obtainMessage();
733 msg.arg1 = OP_DELAYED_MSG;
Wink Savillee68857d2014-10-17 15:23:05 -0700734 msg.arg2 = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800735 mServiceHandler.sendMessage(msg);
736 }
737
Wink Savillee68857d2014-10-17 15:23:05 -0700738 private void callSetActivityInstMsg(int inst_type, int slotId, Object obj) {
739 Message msg = mServiceHandler.obtainMessage();
740 msg.obj = obj;
741 msg.arg1 = inst_type;
742 msg.arg2 = slotId;
743 mServiceHandler.sendMessage(msg);
744 }
745
746 private void handleSessionEnd(int slotId) {
Legler Wuaeefef52014-10-27 00:57:18 +0800747 // We should finish all pending activity if receiving END SESSION command.
748 cleanUpInstanceStackBySlot(slotId);
749
Wink Savillee68857d2014-10-17 15:23:05 -0700750 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
751 CatLog.d(LOG_TAG, "[handleSessionEnd] - mCurrentCmd changed to mMainCmd!.");
752 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mMainCmd;
753 CatLog.d(LOG_TAG, "slotId: " + slotId + ", mMenuState: " +
754 mStkContext[slotId].mMenuState);
755
756 mStkContext[slotId].mIsInputPending = false;
757 mStkContext[slotId].mIsMenuPending = false;
758 mStkContext[slotId].mIsDialogPending = false;
759
Wink Savillee68857d2014-10-17 15:23:05 -0700760 if (mStkContext[slotId].mMainCmd == null) {
761 CatLog.d(LOG_TAG, "[handleSessionEnd][mMainCmd is null!]");
762 }
763 mStkContext[slotId].lastSelectedItem = null;
Wink Saville79085fc2009-06-09 10:27:23 -0700764 // In case of SET UP MENU command which removed the app, don't
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800765 // update the current menu member.
Wink Savillee68857d2014-10-17 15:23:05 -0700766 if (mStkContext[slotId].mCurrentMenu != null && mStkContext[slotId].mMainCmd != null) {
767 mStkContext[slotId].mCurrentMenu = mStkContext[slotId].mMainCmd.getMenu();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800768 }
Wink Savillee68857d2014-10-17 15:23:05 -0700769 CatLog.d(LOG_TAG, "[handleSessionEnd][mMenuState]" + mStkContext[slotId].mMenuIsVisible);
770 // In mutiple instance architecture, the main menu for slotId will be finished when user
771 // goes to the Stk menu of the other SIM. So, we should launch a new instance for the
772 // main menu if the main menu instance has been finished.
773 // If the current menu is secondary menu, we should launch main menu.
774 if (StkMenuActivity.STATE_SECONDARY == mStkContext[slotId].mMenuState) {
775 launchMenuActivity(null, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800776 }
Wink Savillee68857d2014-10-17 15:23:05 -0700777 if (mStkContext[slotId].mCmdsQ.size() != 0) {
778 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800779 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700780 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800781 }
782 // In case a launch browser command was just confirmed, launch that url.
Wink Savillee68857d2014-10-17 15:23:05 -0700783 if (mStkContext[slotId].launchBrowser) {
784 mStkContext[slotId].launchBrowser = false;
785 launchBrowser(mStkContext[slotId].mBrowserSettings);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800786 }
787 }
788
Preeti Ahuja560be362014-11-25 19:38:24 -0800789 // returns true if any Stk related activity already has focus on the screen
790 private boolean isTopOfStack() {
791 ActivityManager mAcivityManager = (ActivityManager) mContext
792 .getSystemService(ACTIVITY_SERVICE);
793 String currentPackageName = mAcivityManager.getRunningTasks(1).get(0).topActivity
794 .getPackageName();
795 if (null != currentPackageName) {
796 return currentPackageName.equals(PACKAGE_NAME);
797 }
798
799 return false;
800 }
801
Wink Savillee68857d2014-10-17 15:23:05 -0700802 private void handleCmd(CatCmdMessage cmdMsg, int slotId) {
Preeti Ahuja95919342013-10-01 18:18:55 -0700803
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800804 if (cmdMsg == null) {
805 return;
806 }
807 // save local reference for state tracking.
Wink Savillee68857d2014-10-17 15:23:05 -0700808 mStkContext[slotId].mCurrentCmd = cmdMsg;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800809 boolean waitForUsersResponse = true;
810
Wink Savillee68857d2014-10-17 15:23:05 -0700811 mStkContext[slotId].mIsInputPending = false;
812 mStkContext[slotId].mIsMenuPending = false;
813 mStkContext[slotId].mIsDialogPending = false;
814
815 CatLog.d(LOG_TAG,"[handleCmd]" + cmdMsg.getCmdType().name());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800816 switch (cmdMsg.getCmdType()) {
817 case DISPLAY_TEXT:
818 TextMessage msg = cmdMsg.geTextMessage();
Jeevaka Badrappan854a25c2012-12-01 16:32:03 +0200819 waitForUsersResponse = msg.responseNeeded;
Wink Savillee68857d2014-10-17 15:23:05 -0700820 if (mStkContext[slotId].lastSelectedItem != null) {
821 msg.title = mStkContext[slotId].lastSelectedItem;
822 } else if (mStkContext[slotId].mMainCmd != null){
823 msg.title = mStkContext[slotId].mMainCmd.getMenu().title;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800824 } else {
825 // TODO: get the carrier name from the SIM
826 msg.title = "";
827 }
Preeti Ahuja560be362014-11-25 19:38:24 -0800828 //If we receive a low priority Display Text and the device is
829 // not displaying any STK related activity and the screen is not idle
830 // ( that is, device is in an interactive state), then send a screen busy
831 // terminal response. Otherwise display the message. The existing
832 // displayed message shall be updated with the new display text
833 // proactive command (Refer to ETSI TS 102 384 section 27.22.4.1.4.4.2).
834 if (!(msg.isHighPriority || mStkContext[slotId].mMenuIsVisible
835 || mStkContext[slotId].mDisplayTextDlgIsVisibile || isTopOfStack())) {
836 if(!isScreenIdle()) {
837 CatLog.d(LOG_TAG, "Screen is not idle");
838 sendScreenBusyResponse(slotId);
839 } else {
840 launchTextDialog(slotId);
841 }
842 } else {
843 launchTextDialog(slotId);
844 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800845 break;
846 case SELECT_ITEM:
Wink Savillee68857d2014-10-17 15:23:05 -0700847 CatLog.d(LOG_TAG, "SELECT_ITEM +");
848 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
849 mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
850 launchMenuActivity(cmdMsg.getMenu(), slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800851 break;
852 case SET_UP_MENU:
Wink Savillee68857d2014-10-17 15:23:05 -0700853 mStkContext[slotId].mCmdInProgress = false;
854 mStkContext[slotId].mMainCmd = mStkContext[slotId].mCurrentCmd;
855 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
856 mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
857 CatLog.d(LOG_TAG, "SET_UP_MENU [" + removeMenu(slotId) + "]");
858
859 if (removeMenu(slotId)) {
860 int i = 0;
861 CatLog.d(LOG_TAG, "removeMenu() - Uninstall App");
862 mStkContext[slotId].mCurrentMenu = null;
Preeti Ahuja95919342013-10-01 18:18:55 -0700863 mStkContext[slotId].mMainCmd = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700864 //Check other setup menu state. If all setup menu are removed, uninstall apk.
865 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
866 if (i != slotId
867 && (mStkContext[slotId].mSetupMenuState == STATE_UNKNOWN
868 || mStkContext[slotId].mSetupMenuState == STATE_EXIST)) {
869 CatLog.d(LOG_TAG, "Not Uninstall App:" + i + ","
870 + mStkContext[slotId].mSetupMenuState);
871 break;
872 }
873 }
874 if (i == mSimCount) {
875 StkAppInstaller.unInstall(mContext);
876 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800877 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700878 CatLog.d(LOG_TAG, "install App");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800879 StkAppInstaller.install(mContext);
880 }
Wink Savillee68857d2014-10-17 15:23:05 -0700881 if (mStkContext[slotId].mMenuIsVisible) {
882 launchMenuActivity(null, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800883 }
884 break;
885 case GET_INPUT:
886 case GET_INKEY:
Wink Savillee68857d2014-10-17 15:23:05 -0700887 launchInputActivity(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800888 break;
889 case SET_UP_IDLE_MODE_TEXT:
890 waitForUsersResponse = false;
Preeti Ahuja560be362014-11-25 19:38:24 -0800891 mStkContext[slotId].mIdleModeTextCmd = mStkContext[slotId].mCurrentCmd;
892 TextMessage idleModeText = mStkContext[slotId].mCurrentCmd.geTextMessage();
893 if (idleModeText == null) {
894 launchIdleText(slotId);
895 mStkContext[slotId].mIdleModeTextCmd = null;
896 }
897 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
898 if ((mStkContext[slotId].mIdleModeTextCmd != null) && isScreenIdle()) {
899 CatLog.d(this, "set up idle mode");
900 launchIdleText(slotId);
901 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800902 break;
903 case SEND_DTMF:
904 case SEND_SMS:
905 case SEND_SS:
906 case SEND_USSD:
Preeti Ahuja95919342013-10-01 18:18:55 -0700907 case GET_CHANNEL_STATUS:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800908 waitForUsersResponse = false;
Wink Savillee68857d2014-10-17 15:23:05 -0700909 launchEventMessage(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800910 break;
911 case LAUNCH_BROWSER:
Wink Savillee68857d2014-10-17 15:23:05 -0700912 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.geTextMessage(), slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800913 break;
914 case SET_UP_CALL:
Preeti Ahujadd240102013-08-30 17:25:06 -0700915 TextMessage mesg = mStkContext[slotId].mCurrentCmd.getCallSettings().confirmMsg;
916 if((mesg != null) && (mesg.text == null || mesg.text.length() == 0)) {
917 mesg.text = getResources().getString(R.string.default_setup_call_msg);
918 }
919 CatLog.d(this, "SET_UP_CALL mesg.text " + mesg.text);
920 launchConfirmationDialog(mesg, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800921 break;
922 case PLAY_TONE:
Wink Savillee68857d2014-10-17 15:23:05 -0700923 launchToneDialog(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800924 break;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500925 case OPEN_CHANNEL:
Wink Savillee68857d2014-10-17 15:23:05 -0700926 launchOpenChannelDialog(slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500927 break;
928 case CLOSE_CHANNEL:
929 case RECEIVE_DATA:
930 case SEND_DATA:
Wink Savillee68857d2014-10-17 15:23:05 -0700931 TextMessage m = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500932
933 if ((m != null) && (m.text == null)) {
934 switch(cmdMsg.getCmdType()) {
935 case CLOSE_CHANNEL:
936 m.text = getResources().getString(R.string.default_close_channel_msg);
937 break;
938 case RECEIVE_DATA:
939 m.text = getResources().getString(R.string.default_receive_data_msg);
940 break;
941 case SEND_DATA:
942 m.text = getResources().getString(R.string.default_send_data_msg);
943 break;
944 }
945 }
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -0700946 /*
947 * Display indication in the form of a toast to the user if required.
948 */
Wink Savillee68857d2014-10-17 15:23:05 -0700949 launchEventMessage(slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500950 break;
Preeti Ahuja95919342013-10-01 18:18:55 -0700951 case SET_UP_EVENT_LIST:
952 mStkContext[slotId].mSetupEventListSettings =
953 mStkContext[slotId].mCurrentCmd.getSetEventList();
954 mStkContext[slotId].mCurrentSetupEventCmd = mStkContext[slotId].mCurrentCmd;
955 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
Preeti Ahuja560be362014-11-25 19:38:24 -0800956 if (isScreenIdle()) {
957 CatLog.d(this," Check if IDLE_SCREEN_AVAILABLE_EVENT is present in List");
958 checkForSetupEvent(IDLE_SCREEN_AVAILABLE_EVENT, null, slotId);
959 }
Preeti Ahuja95919342013-10-01 18:18:55 -0700960 break;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800961 }
962
963 if (!waitForUsersResponse) {
Wink Savillee68857d2014-10-17 15:23:05 -0700964 if (mStkContext[slotId].mCmdsQ.size() != 0) {
965 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800966 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700967 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800968 }
969 }
970 }
971
Wink Savillee68857d2014-10-17 15:23:05 -0700972 private void handleCmdResponse(Bundle args, int slotId) {
973 CatLog.d(LOG_TAG, "handleCmdResponse, sim id: " + slotId);
974 if (mStkContext[slotId].mCurrentCmd == null) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800975 return;
976 }
Wink Savillee68857d2014-10-17 15:23:05 -0700977
978 if (mStkService[slotId] == null) {
Legler Wuaeefef52014-10-27 00:57:18 +0800979 mStkService[slotId] = CatService.getInstance(slotId);
Wink Savillee68857d2014-10-17 15:23:05 -0700980 if (mStkService[slotId] == null) {
Alex Yakavenkad8e2ecd2012-04-20 17:10:15 -0700981 // This should never happen (we should be responding only to a message
982 // that arrived from StkService). It has to exist by this time
Wink Savillee68857d2014-10-17 15:23:05 -0700983 CatLog.d(LOG_TAG, "Exception! mStkService is null when we need to send response.");
Alex Yakavenkad8e2ecd2012-04-20 17:10:15 -0700984 throw new RuntimeException("mStkService is null when we need to send response");
985 }
986 }
987
Wink Savillee68857d2014-10-17 15:23:05 -0700988 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentCmd);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800989
990 // set result code
991 boolean helpRequired = args.getBoolean(HELP, false);
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -0700992 boolean confirmed = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800993
994 switch(args.getInt(RES_ID)) {
995 case RES_ID_MENU_SELECTION:
Wink Savillee68857d2014-10-17 15:23:05 -0700996 CatLog.d(LOG_TAG, "MENU_SELECTION=" + mStkContext[slotId].
997 mCurrentMenuCmd.getCmdType());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800998 int menuSelection = args.getInt(MENU_SELECTION);
Wink Savillee68857d2014-10-17 15:23:05 -0700999 switch(mStkContext[slotId].mCurrentMenuCmd.getCmdType()) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001000 case SET_UP_MENU:
1001 case SELECT_ITEM:
Wink Savillee68857d2014-10-17 15:23:05 -07001002 mStkContext[slotId].lastSelectedItem = getItemName(menuSelection, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001003 if (helpRequired) {
1004 resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
1005 } else {
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301006 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1007 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001008 }
1009 resMsg.setMenuSelection(menuSelection);
1010 break;
1011 }
1012 break;
1013 case RES_ID_INPUT:
Wink Savillee68857d2014-10-17 15:23:05 -07001014 CatLog.d(LOG_TAG, "RES_ID_INPUT");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001015 String input = args.getString(INPUT);
Wink Savillee68857d2014-10-17 15:23:05 -07001016 if (input != null && (null != mStkContext[slotId].mCurrentCmd.geInput()) &&
1017 (mStkContext[slotId].mCurrentCmd.geInput().yesNo)) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001018 boolean yesNoSelection = input
1019 .equals(StkInputActivity.YES_STR_RESPONSE);
1020 resMsg.setYesNo(yesNoSelection);
1021 } else {
1022 if (helpRequired) {
1023 resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
1024 } else {
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301025 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1026 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001027 resMsg.setInput(input);
1028 }
1029 }
1030 break;
1031 case RES_ID_CONFIRM:
Alex Yakavenkad41f1d92010-07-12 14:13:13 -07001032 CatLog.d(this, "RES_ID_CONFIRM");
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001033 confirmed = args.getBoolean(CONFIRMATION);
Wink Savillee68857d2014-10-17 15:23:05 -07001034 switch (mStkContext[slotId].mCurrentCmd.getCmdType()) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001035 case DISPLAY_TEXT:
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301036 if (confirmed) {
1037 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1038 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
1039 } else {
1040 resMsg.setResultCode(ResultCode.UICC_SESSION_TERM_BY_USER);
1041 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001042 break;
1043 case LAUNCH_BROWSER:
1044 resMsg.setResultCode(confirmed ? ResultCode.OK
1045 : ResultCode.UICC_SESSION_TERM_BY_USER);
1046 if (confirmed) {
Wink Savillee68857d2014-10-17 15:23:05 -07001047 mStkContext[slotId].launchBrowser = true;
1048 mStkContext[slotId].mBrowserSettings =
1049 mStkContext[slotId].mCurrentCmd.getBrowserSettings();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001050 }
1051 break;
1052 case SET_UP_CALL:
1053 resMsg.setResultCode(ResultCode.OK);
1054 resMsg.setConfirmation(confirmed);
1055 if (confirmed) {
w302345ad585e2014-11-04 12:13:38 -08001056 CatLog.d(this, "Going back to mainMenu before starting a call.");
1057 launchMenuActivity(null, slotId);
Wink Savillee68857d2014-10-17 15:23:05 -07001058 launchEventMessage(slotId,
1059 mStkContext[slotId].mCurrentCmd.getCallSettings().callMsg);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001060 }
1061 break;
1062 }
1063 break;
1064 case RES_ID_DONE:
1065 resMsg.setResultCode(ResultCode.OK);
1066 break;
1067 case RES_ID_BACKWARD:
Wink Savillee68857d2014-10-17 15:23:05 -07001068 CatLog.d(LOG_TAG, "RES_ID_BACKWARD");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001069 resMsg.setResultCode(ResultCode.BACKWARD_MOVE_BY_USER);
1070 break;
1071 case RES_ID_END_SESSION:
Wink Savillee68857d2014-10-17 15:23:05 -07001072 CatLog.d(LOG_TAG, "RES_ID_END_SESSION");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001073 resMsg.setResultCode(ResultCode.UICC_SESSION_TERM_BY_USER);
1074 break;
1075 case RES_ID_TIMEOUT:
Wink Savillee68857d2014-10-17 15:23:05 -07001076 CatLog.d(LOG_TAG, "RES_ID_TIMEOUT");
Naveen Kallad5176892009-11-30 12:45:29 -08001077 // GCF test-case 27.22.4.1.1 Expected Sequence 1.5 (DISPLAY TEXT,
1078 // Clear message after delay, successful) expects result code OK.
1079 // If the command qualifier specifies no user response is required
1080 // then send OK instead of NO_RESPONSE_FROM_USER
Wink Savillee68857d2014-10-17 15:23:05 -07001081 if ((mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1082 AppInterface.CommandType.DISPLAY_TEXT.value())
1083 && (mStkContext[slotId].mCurrentCmd.geTextMessage().userClear == false)) {
Naveen Kallad5176892009-11-30 12:45:29 -08001084 resMsg.setResultCode(ResultCode.OK);
1085 } else {
1086 resMsg.setResultCode(ResultCode.NO_RESPONSE_FROM_USER);
1087 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001088 break;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001089 case RES_ID_CHOICE:
1090 int choice = args.getInt(CHOICE);
1091 CatLog.d(this, "User Choice=" + choice);
1092 switch (choice) {
1093 case YES:
1094 resMsg.setResultCode(ResultCode.OK);
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001095 confirmed = true;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001096 break;
1097 case NO:
1098 resMsg.setResultCode(ResultCode.USER_NOT_ACCEPT);
1099 break;
1100 }
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001101
Wink Savillee68857d2014-10-17 15:23:05 -07001102 if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1103 AppInterface.CommandType.OPEN_CHANNEL.value()) {
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001104 resMsg.setConfirmation(confirmed);
1105 }
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001106 break;
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001107
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001108 default:
Wink Savillee68857d2014-10-17 15:23:05 -07001109 CatLog.d(LOG_TAG, "Unknown result id");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001110 return;
1111 }
Wink Savillee68857d2014-10-17 15:23:05 -07001112
1113 if (null != mStkContext[slotId].mCurrentCmd &&
1114 null != mStkContext[slotId].mCurrentCmd.getCmdType()) {
1115 CatLog.d(LOG_TAG, "handleCmdResponse- cmdName[" +
1116 mStkContext[slotId].mCurrentCmd.getCmdType().name() + "]");
1117 }
1118 mStkService[slotId].onCmdResponse(resMsg);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001119 }
1120
1121 /**
1122 * Returns 0 or FLAG_ACTIVITY_NO_USER_ACTION, 0 means the user initiated the action.
1123 *
1124 * @param userAction If the userAction is yes then we always return 0 otherwise
1125 * mMenuIsVisible is used to determine what to return. If mMenuIsVisible is true
1126 * then we are the foreground app and we'll return 0 as from our perspective a
1127 * user action did cause. If it's false than we aren't the foreground app and
1128 * FLAG_ACTIVITY_NO_USER_ACTION is returned.
Wink Saville79085fc2009-06-09 10:27:23 -07001129 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001130 * @return 0 or FLAG_ACTIVITY_NO_USER_ACTION
1131 */
Wink Savillee68857d2014-10-17 15:23:05 -07001132 private int getFlagActivityNoUserAction(InitiatedByUserAction userAction, int slotId) {
1133 return ((userAction == InitiatedByUserAction.yes) | mStkContext[slotId].mMenuIsVisible)
1134 ? 0 : Intent.FLAG_ACTIVITY_NO_USER_ACTION;
1135 }
1136 /**
1137 * This method is used for cleaning up pending instances in stack.
1138 */
1139 private void cleanUpInstanceStackBySlot(int slotId) {
1140 Activity activity = mStkContext[slotId].getPendingActivityInstance();
1141 Activity dialog = mStkContext[slotId].getPendingDialogInstance();
1142 CatLog.d(LOG_TAG, "cleanUpInstanceStackBySlot slotId: " + slotId);
Legler Wuaeefef52014-10-27 00:57:18 +08001143 if (mStkContext[slotId].mCurrentCmd == null) {
1144 CatLog.d(LOG_TAG, "current cmd is null.");
1145 return;
1146 }
Wink Savillee68857d2014-10-17 15:23:05 -07001147 if (activity != null) {
1148 CatLog.d(LOG_TAG, "current cmd type: " +
1149 mStkContext[slotId].mCurrentCmd.getCmdType());
1150 if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1151 AppInterface.CommandType.GET_INPUT.value() ||
1152 mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1153 AppInterface.CommandType.GET_INKEY.value()) {
1154 mStkContext[slotId].mIsInputPending = true;
1155 } else if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1156 AppInterface.CommandType.SET_UP_MENU.value() ||
1157 mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1158 AppInterface.CommandType.SELECT_ITEM.value()) {
1159 mStkContext[slotId].mIsMenuPending = true;
1160 } else {
1161 }
1162 CatLog.d(LOG_TAG, "finish pending activity.");
1163 activity.finish();
1164 mStkContext[slotId].mActivityInstance = null;
1165 }
1166 if (dialog != null) {
1167 CatLog.d(LOG_TAG, "finish pending dialog.");
1168 mStkContext[slotId].mIsDialogPending = true;
1169 dialog.finish();
1170 mStkContext[slotId].mDialogInstance = null;
1171 }
1172 }
1173 /**
1174 * This method is used for restoring pending instances from stack.
1175 */
1176 private void restoreInstanceFromStackBySlot(int slotId) {
1177 AppInterface.CommandType cmdType = mStkContext[slotId].mCurrentCmd.getCmdType();
1178
1179 CatLog.d(LOG_TAG, "restoreInstanceFromStackBySlot cmdType : " + cmdType);
1180 switch(cmdType) {
1181 case GET_INPUT:
1182 case GET_INKEY:
1183 launchInputActivity(slotId);
1184 //Set mMenuIsVisible to true for showing main menu for
1185 //following session end command.
1186 mStkContext[slotId].mMenuIsVisible = true;
1187 break;
1188 case DISPLAY_TEXT:
1189 launchTextDialog(slotId);
1190 break;
1191 case LAUNCH_BROWSER:
1192 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.geTextMessage(),
1193 slotId);
1194 break;
1195 case OPEN_CHANNEL:
1196 launchOpenChannelDialog(slotId);
1197 break;
1198 case SET_UP_CALL:
1199 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.getCallSettings().
1200 confirmMsg, slotId);
1201 break;
1202 case SET_UP_MENU:
1203 case SELECT_ITEM:
1204 launchMenuActivity(null, slotId);
1205 break;
1206 default:
1207 break;
1208 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001209 }
1210
Wink Savillee68857d2014-10-17 15:23:05 -07001211 private void launchMenuActivity(Menu menu, int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001212 Intent newIntent = new Intent(Intent.ACTION_VIEW);
Wink Savillee68857d2014-10-17 15:23:05 -07001213 String targetActivity = STK_MENU_ACTIVITY_NAME;
1214 String uriString = STK_MENU_URI + System.currentTimeMillis();
1215 //Set unique URI to create a new instance of activity for different slotId.
1216 Uri uriData = Uri.parse(uriString);
1217
1218 CatLog.d(LOG_TAG, "launchMenuActivity, slotId: " + slotId + " , " +
1219 uriData.toString() + " , " + mStkContext[slotId].mOpCode + ", "
1220 + mStkContext[slotId].mMenuState);
1221 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1222 int intentFlags = Intent.FLAG_ACTIVITY_NEW_TASK;
1223
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001224 if (menu == null) {
1225 // We assume this was initiated by the user pressing the tool kit icon
Wink Savillee68857d2014-10-17 15:23:05 -07001226 intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.yes, slotId);
1227 if (mStkContext[slotId].mOpCode == OP_END_SESSION) {
1228 CatLog.d(LOG_TAG, "launchMenuActivity, return OP_END_SESSION");
1229 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
1230 if (mStkContext[slotId].mMainActivityInstance != null) {
1231 CatLog.d(LOG_TAG, "launchMenuActivity, mMainActivityInstance is not null");
1232 return;
1233 }
Wink Savillee68857d2014-10-17 15:23:05 -07001234 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001235
Wink Savillee68857d2014-10-17 15:23:05 -07001236 //If the last pending menu is secondary menu, "STATE" should be "STATE_SECONDARY".
1237 //Otherwise, it should be "STATE_MAIN".
1238 if (mStkContext[slotId].mOpCode == OP_LAUNCH_APP &&
1239 mStkContext[slotId].mMenuState == StkMenuActivity.STATE_SECONDARY) {
1240 newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
1241 } else {
1242 newIntent.putExtra("STATE", StkMenuActivity.STATE_MAIN);
1243 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
1244 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001245 } else {
1246 // We don't know and we'll let getFlagActivityNoUserAction decide.
Wink Savillee68857d2014-10-17 15:23:05 -07001247 intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001248 newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
Wink Savillee68857d2014-10-17 15:23:05 -07001249 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_SECONDARY;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001250 }
Wink Savillee68857d2014-10-17 15:23:05 -07001251 newIntent.putExtra(SLOT_ID, slotId);
1252 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001253 newIntent.setFlags(intentFlags);
1254 mContext.startActivity(newIntent);
1255 }
1256
Wink Savillee68857d2014-10-17 15:23:05 -07001257 private void launchInputActivity(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001258 Intent newIntent = new Intent(Intent.ACTION_VIEW);
Wink Savillee68857d2014-10-17 15:23:05 -07001259 String targetActivity = STK_INPUT_ACTIVITY_NAME;
1260 String uriString = STK_INPUT_URI + System.currentTimeMillis();
1261 //Set unique URI to create a new instance of activity for different slotId.
1262 Uri uriData = Uri.parse(uriString);
1263
1264 CatLog.d(LOG_TAG, "launchInputActivity, slotId: " + slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001265 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
Wink Savillee68857d2014-10-17 15:23:05 -07001266 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1267 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1268 newIntent.putExtra("INPUT", mStkContext[slotId].mCurrentCmd.geInput());
1269 newIntent.putExtra(SLOT_ID, slotId);
1270 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001271 mContext.startActivity(newIntent);
1272 }
1273
Wink Savillee68857d2014-10-17 15:23:05 -07001274 private void launchTextDialog(int slotId) {
1275 CatLog.d(LOG_TAG, "launchTextDialog, slotId: " + slotId);
1276 Intent newIntent = new Intent();
1277 String targetActivity = STK_DIALOG_ACTIVITY_NAME;
1278 int action = getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
1279 String uriString = STK_DIALOG_URI + System.currentTimeMillis();
1280 //Set unique URI to create a new instance of activity for different slotId.
1281 Uri uriData = Uri.parse(uriString);
1282 if (newIntent != null) {
1283 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1284 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1285 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
1286 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1287 newIntent.setData(uriData);
1288 newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
1289 newIntent.putExtra(SLOT_ID, slotId);
1290 startActivity(newIntent);
Preeti Ahuja414bc412013-06-25 19:31:49 -07001291 // For display texts with immediate response, send the terminal response
1292 // immediately. responseNeeded will be false, if display text command has
1293 // the immediate response tlv.
1294 if (!mStkContext[slotId].mCurrentCmd.geTextMessage().responseNeeded) {
1295 sendResponse(RES_ID_CONFIRM, slotId, true);
1296 }
Wink Savillee68857d2014-10-17 15:23:05 -07001297 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001298 }
1299
Wink Savillee68857d2014-10-17 15:23:05 -07001300 public boolean isStkDialogActivated(Context context) {
1301 String stkDialogActivity = "com.android.stk.StkDialogActivity";
1302 boolean activated = false;
1303 final ActivityManager am = (ActivityManager) context.getSystemService(
1304 Context.ACTIVITY_SERVICE);
1305 String topActivity = am.getRunningTasks(1).get(0).topActivity.getClassName();
1306
1307 CatLog.d(LOG_TAG, "isStkDialogActivated: " + topActivity);
1308 if (topActivity.equals(stkDialogActivity)) {
1309 activated = true;
1310 }
1311 CatLog.d(LOG_TAG, "activated : " + activated);
1312 return activated;
Johan Hellman3aec01c2011-02-10 10:15:28 +01001313 }
1314
Preeti Ahuja95919342013-10-01 18:18:55 -07001315 private void sendSetUpEventResponse(int event, byte[] addedInfo, int slotId) {
Preeti Ahuja414bc412013-06-25 19:31:49 -07001316 CatLog.d(this, "sendSetUpEventResponse: event : " + event + "slotId = " + slotId);
Preeti Ahuja95919342013-10-01 18:18:55 -07001317
1318 if (mStkContext[slotId].mCurrentSetupEventCmd == null){
1319 CatLog.e(this, "mCurrentSetupEventCmd is null");
1320 return;
1321 }
1322
1323 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentSetupEventCmd);
1324
1325 resMsg.setResultCode(ResultCode.OK);
1326 resMsg.setEventDownload(event, addedInfo);
1327
1328 mStkService[slotId].onCmdResponse(resMsg);
1329 }
1330
1331 private void checkForSetupEvent(int event, Bundle args, int slotId) {
1332 boolean eventPresent = false;
1333 byte[] addedInfo = null;
1334 CatLog.d(this, "Event :" + event);
1335
1336 if (mStkContext[slotId].mSetupEventListSettings != null) {
1337 /* Checks if the event is present in the EventList updated by last
1338 * SetupEventList Proactive Command */
1339 for (int i : mStkContext[slotId].mSetupEventListSettings.eventList) {
1340 if (event == i) {
1341 eventPresent = true;
1342 break;
1343 }
1344 }
1345
1346 /* If Event is present send the response to ICC */
1347 if (eventPresent == true) {
1348 CatLog.d(this, " Event " + event + "exists in the EventList");
1349
1350 switch (event) {
Preeti Ahuja560be362014-11-25 19:38:24 -08001351 case IDLE_SCREEN_AVAILABLE_EVENT:
1352 sendSetUpEventResponse(event, addedInfo, slotId);
1353 removeSetUpEvent(event, slotId);
1354 break;
Preeti Ahuja95919342013-10-01 18:18:55 -07001355 case LANGUAGE_SELECTION_EVENT:
1356 String language = mContext
1357 .getResources().getConfiguration().locale.getLanguage();
1358 CatLog.d(this, "language: " + language);
1359 // Each language code is a pair of alpha-numeric characters.
1360 // Each alpha-numeric character shall be coded on one byte
1361 // using the SMS default 7-bit coded alphabet
1362 addedInfo = GsmAlphabet.stringToGsm8BitPacked(language);
1363 sendSetUpEventResponse(event, addedInfo, slotId);
1364 break;
1365 default:
1366 break;
1367 }
1368 } else {
1369 CatLog.e(this, " Event does not exist in the EventList");
1370 }
1371 } else {
1372 CatLog.e(this, "SetupEventList is not received. Ignoring the event: " + event);
1373 }
1374 }
1375
1376 private void removeSetUpEvent(int event, int slotId) {
1377 CatLog.d(this, "Remove Event :" + event);
1378
1379 if (mStkContext[slotId].mSetupEventListSettings != null) {
1380 /*
1381 * Make new Eventlist without the event
1382 */
1383 for (int i = 0; i < mStkContext[slotId].mSetupEventListSettings.eventList.length; i++) {
1384 if (event == mStkContext[slotId].mSetupEventListSettings.eventList[i]) {
1385 mStkContext[slotId].mSetupEventListSettings.eventList[i] = INVALID_SETUP_EVENT;
1386 break;
1387 }
1388 }
1389 }
1390 }
1391
1392 private void launchEventMessage(int slotId) {
1393 launchEventMessage(slotId, mStkContext[slotId].mCurrentCmd.geTextMessage());
1394 }
1395
Wink Savillee68857d2014-10-17 15:23:05 -07001396 private void launchEventMessage(int slotId, TextMessage msg) {
1397 if (msg == null || (msg.text != null && msg.text.length() == 0)) {
1398 CatLog.d(LOG_TAG, "launchEventMessage return");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001399 return;
1400 }
Wink Savillee68857d2014-10-17 15:23:05 -07001401
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001402 Toast toast = new Toast(mContext.getApplicationContext());
1403 LayoutInflater inflate = (LayoutInflater) mContext
1404 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
1405 View v = inflate.inflate(R.layout.stk_event_msg, null);
1406 TextView tv = (TextView) v
1407 .findViewById(com.android.internal.R.id.message);
1408 ImageView iv = (ImageView) v
1409 .findViewById(com.android.internal.R.id.icon);
1410 if (msg.icon != null) {
1411 iv.setImageBitmap(msg.icon);
1412 } else {
1413 iv.setVisibility(View.GONE);
1414 }
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301415 /* In case of 'self explanatory' stkapp should display the specified
1416 * icon in proactive command (but not the alpha string).
1417 * If icon is non-self explanatory and if the icon could not be displayed
1418 * then alpha string or text data should be displayed
1419 * Ref: ETSI 102.223,section 6.5.4
1420 */
1421 if (mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ||
1422 msg.icon == null || !msg.iconSelfExplanatory) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001423 tv.setText(msg.text);
1424 }
1425
1426 toast.setView(v);
1427 toast.setDuration(Toast.LENGTH_LONG);
1428 toast.setGravity(Gravity.BOTTOM, 0, 0);
1429 toast.show();
1430 }
1431
Wink Savillee68857d2014-10-17 15:23:05 -07001432 private void launchConfirmationDialog(TextMessage msg, int slotId) {
1433 msg.title = mStkContext[slotId].lastSelectedItem;
1434 Intent newIntent = new Intent();
1435 String targetActivity = STK_DIALOG_ACTIVITY_NAME;
1436 String uriString = STK_DIALOG_URI + System.currentTimeMillis();
1437 //Set unique URI to create a new instance of activity for different slotId.
1438 Uri uriData = Uri.parse(uriString);
1439
1440 if (newIntent != null) {
1441 newIntent.setClassName(this, targetActivity);
1442 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1443 | Intent.FLAG_ACTIVITY_NO_HISTORY
1444 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
1445 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1446 newIntent.putExtra("TEXT", msg);
1447 newIntent.putExtra(SLOT_ID, slotId);
1448 newIntent.setData(uriData);
1449 startActivity(newIntent);
1450 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001451 }
1452
1453 private void launchBrowser(BrowserSettings settings) {
1454 if (settings == null) {
1455 return;
1456 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001457
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001458 Intent intent = null;
1459 Uri data = null;
David Brown7c03cfe2011-10-20 15:36:12 -07001460
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001461 if (settings.url != null) {
Wink Savillee68857d2014-10-17 15:23:05 -07001462 CatLog.d(LOG_TAG, "settings.url = " + settings.url);
dujin.cha2a0eb2a2011-11-11 15:03:57 +09001463 if ((settings.url.startsWith("http://") || (settings.url.startsWith("https://")))) {
dujin.cha486c1d02011-11-02 22:14:25 +09001464 data = Uri.parse(settings.url);
1465 } else {
1466 String modifiedUrl = "http://" + settings.url;
Wink Savillee68857d2014-10-17 15:23:05 -07001467 CatLog.d(LOG_TAG, "modifiedUrl = " + modifiedUrl);
dujin.cha486c1d02011-11-02 22:14:25 +09001468 data = Uri.parse(modifiedUrl);
1469 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001470 }
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001471 if (data != null) {
1472 intent = new Intent(Intent.ACTION_VIEW);
1473 intent.setData(data);
1474 } else {
1475 // if the command did not contain a URL,
1476 // launch the browser to the default homepage.
Wink Savillee68857d2014-10-17 15:23:05 -07001477 CatLog.d(LOG_TAG, "launch browser with default URL ");
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001478 intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN,
1479 Intent.CATEGORY_APP_BROWSER);
1480 }
David Brown7c03cfe2011-10-20 15:36:12 -07001481
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001482 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1483 switch (settings.mode) {
1484 case USE_EXISTING_BROWSER:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001485 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1486 break;
1487 case LAUNCH_NEW_BROWSER:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001488 intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
1489 break;
1490 case LAUNCH_IF_NOT_ALREADY_LAUNCHED:
1491 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1492 break;
1493 }
1494 // start browser activity
1495 startActivity(intent);
1496 // a small delay, let the browser start, before processing the next command.
Wink Saville79085fc2009-06-09 10:27:23 -07001497 // this is good for scenarios where a related DISPLAY TEXT command is
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001498 // followed immediately.
1499 try {
1500 Thread.sleep(10000);
1501 } catch (InterruptedException e) {}
1502 }
1503
Wink Savillee68857d2014-10-17 15:23:05 -07001504 private void launchIdleText(int slotId) {
Preeti Ahuja560be362014-11-25 19:38:24 -08001505 TextMessage msg = mStkContext[slotId].mIdleModeTextCmd.geTextMessage();
dujin.cha2a0eb2a2011-11-11 15:03:57 +09001506
Preeti Ahuja95919342013-10-01 18:18:55 -07001507 if (msg == null || msg.text ==null) {
1508 CatLog.d(LOG_TAG, msg == null ? "mCurrent.getTextMessage is NULL"
1509 : "mCurrent.getTextMessage.text is NULL");
Wink Savillee68857d2014-10-17 15:23:05 -07001510 mNotificationManager.cancel(getNotificationId(slotId));
Wink Saville046db4b2011-11-01 20:42:54 -07001511 return;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001512 } else {
Preeti Ahuja95919342013-10-01 18:18:55 -07001513 CatLog.d(LOG_TAG, "launchIdleText - text[" + msg.text
1514 + "] iconSelfExplanatory[" + msg.iconSelfExplanatory
1515 + "] icon[" + msg.icon + "], sim id: " + slotId);
Wink Savillee68857d2014-10-17 15:23:05 -07001516 CatLog.d(LOG_TAG, "Add IdleMode text");
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001517 PendingIntent pendingIntent = PendingIntent.getService(mContext, 0,
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001518 new Intent(mContext, StkAppService.class), 0);
1519
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001520 final Notification.Builder notificationBuilder = new Notification.Builder(
1521 StkAppService.this);
Wink Savillee68857d2014-10-17 15:23:05 -07001522 if (mStkContext[slotId].mMainCmd != null &&
1523 mStkContext[slotId].mMainCmd.getMenu() != null) {
1524 notificationBuilder.setContentTitle(mStkContext[slotId].mMainCmd.getMenu().title);
Christopher Posselwhite2ad2ab72013-05-27 07:51:06 +02001525 } else {
1526 notificationBuilder.setContentTitle("");
1527 }
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001528 notificationBuilder
1529 .setSmallIcon(com.android.internal.R.drawable.stat_notify_sim_toolkit);
1530 notificationBuilder.setContentIntent(pendingIntent);
1531 notificationBuilder.setOngoing(true);
1532 // Set text and icon for the status bar and notification body.
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301533 if (mStkContext[slotId].mIdleModeTextCmd.hasIconLoadFailed() ||
1534 !msg.iconSelfExplanatory) {
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001535 notificationBuilder.setContentText(msg.text);
Christopher Posselwhite2ad2ab72013-05-27 07:51:06 +02001536 notificationBuilder.setTicker(msg.text);
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001537 }
1538 if (msg.icon != null) {
1539 notificationBuilder.setLargeIcon(msg.icon);
1540 } else {
1541 Bitmap bitmapIcon = BitmapFactory.decodeResource(StkAppService.this
1542 .getResources().getSystem(),
1543 com.android.internal.R.drawable.stat_notify_sim_toolkit);
1544 notificationBuilder.setLargeIcon(bitmapIcon);
1545 }
Selim Cinek62eb3fe2014-08-27 17:52:23 +02001546 notificationBuilder.setColor(mContext.getResources().getColor(
1547 com.android.internal.R.color.system_notification_accent_color));
Wink Savillee68857d2014-10-17 15:23:05 -07001548 mNotificationManager.notify(getNotificationId(slotId), notificationBuilder.build());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001549 }
1550 }
1551
Wink Savillee68857d2014-10-17 15:23:05 -07001552 private void launchToneDialog(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001553 Intent newIntent = new Intent(this, ToneDialog.class);
Wink Savillee68857d2014-10-17 15:23:05 -07001554 String uriString = STK_TONE_URI + slotId;
1555 Uri uriData = Uri.parse(uriString);
1556 //Set unique URI to create a new instance of activity for different slotId.
1557 CatLog.d(LOG_TAG, "launchToneDialog, slotId: " + slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001558 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1559 | Intent.FLAG_ACTIVITY_NO_HISTORY
1560 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
Wink Savillee68857d2014-10-17 15:23:05 -07001561 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1562 newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
1563 newIntent.putExtra("TONE", mStkContext[slotId].mCurrentCmd.getToneSettings());
1564 newIntent.putExtra(SLOT_ID, slotId);
1565 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001566 startActivity(newIntent);
1567 }
1568
Wink Savillee68857d2014-10-17 15:23:05 -07001569 private void launchOpenChannelDialog(int slotId) {
1570 TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001571 if (msg == null) {
Wink Savillee68857d2014-10-17 15:23:05 -07001572 CatLog.d(LOG_TAG, "msg is null, return here");
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001573 return;
1574 }
1575
1576 msg.title = getResources().getString(R.string.stk_dialog_title);
1577 if (msg.text == null) {
1578 msg.text = getResources().getString(R.string.default_open_channel_msg);
1579 }
1580
1581 final AlertDialog dialog = new AlertDialog.Builder(mContext)
1582 .setIconAttribute(android.R.attr.alertDialogIcon)
1583 .setTitle(msg.title)
1584 .setMessage(msg.text)
1585 .setCancelable(false)
1586 .setPositiveButton(getResources().getString(R.string.stk_dialog_accept),
1587 new DialogInterface.OnClickListener() {
1588 public void onClick(DialogInterface dialog, int which) {
1589 Bundle args = new Bundle();
1590 args.putInt(RES_ID, RES_ID_CHOICE);
1591 args.putInt(CHOICE, YES);
1592 Message message = mServiceHandler.obtainMessage();
1593 message.arg1 = OP_RESPONSE;
1594 message.obj = args;
1595 mServiceHandler.sendMessage(message);
1596 }
1597 })
1598 .setNegativeButton(getResources().getString(R.string.stk_dialog_reject),
1599 new DialogInterface.OnClickListener() {
1600 public void onClick(DialogInterface dialog, int which) {
1601 Bundle args = new Bundle();
1602 args.putInt(RES_ID, RES_ID_CHOICE);
1603 args.putInt(CHOICE, NO);
1604 Message message = mServiceHandler.obtainMessage();
1605 message.arg1 = OP_RESPONSE;
1606 message.obj = args;
1607 mServiceHandler.sendMessage(message);
1608 }
1609 })
1610 .create();
1611
1612 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1613 if (!mContext.getResources().getBoolean(
1614 com.android.internal.R.bool.config_sf_slowBlur)) {
1615 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
1616 }
1617
1618 dialog.show();
1619 }
1620
Wink Savillee68857d2014-10-17 15:23:05 -07001621 private void launchTransientEventMessage(int slotId) {
1622 TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001623 if (msg == null) {
Wink Savillee68857d2014-10-17 15:23:05 -07001624 CatLog.d(LOG_TAG, "msg is null, return here");
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001625 return;
1626 }
1627
1628 msg.title = getResources().getString(R.string.stk_dialog_title);
1629
1630 final AlertDialog dialog = new AlertDialog.Builder(mContext)
1631 .setIconAttribute(android.R.attr.alertDialogIcon)
1632 .setTitle(msg.title)
1633 .setMessage(msg.text)
1634 .setCancelable(false)
1635 .setPositiveButton(getResources().getString(android.R.string.ok),
1636 new DialogInterface.OnClickListener() {
1637 public void onClick(DialogInterface dialog, int which) {
1638 }
1639 })
1640 .create();
1641
1642 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1643 if (!mContext.getResources().getBoolean(
1644 com.android.internal.R.bool.config_sf_slowBlur)) {
1645 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
1646 }
1647
1648 dialog.show();
1649 }
1650
Wink Savillee68857d2014-10-17 15:23:05 -07001651 private int getNotificationId(int slotId) {
1652 int notifyId = STK_NOTIFICATION_ID;
1653 if (slotId >= 0 && slotId < mSimCount) {
1654 notifyId += slotId;
1655 } else {
1656 CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
1657 }
1658 CatLog.d(LOG_TAG, "getNotificationId, slotId: " + slotId + ", notifyId: " + notifyId);
1659 return notifyId;
1660 }
1661
1662 private String getItemName(int itemId, int slotId) {
1663 Menu menu = mStkContext[slotId].mCurrentCmd.getMenu();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001664 if (menu == null) {
1665 return null;
1666 }
1667 for (Item item : menu.items) {
1668 if (item.id == itemId) {
1669 return item.text;
1670 }
1671 }
1672 return null;
1673 }
1674
Wink Savillee68857d2014-10-17 15:23:05 -07001675 private boolean removeMenu(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001676 try {
Wink Savillee68857d2014-10-17 15:23:05 -07001677 if (mStkContext[slotId].mCurrentMenu.items.size() == 1 &&
1678 mStkContext[slotId].mCurrentMenu.items.get(0) == null) {
1679 mStkContext[slotId].mSetupMenuState = STATE_NOT_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001680 return true;
1681 }
1682 } catch (NullPointerException e) {
Wink Savillee68857d2014-10-17 15:23:05 -07001683 CatLog.d(LOG_TAG, "Unable to get Menu's items size");
1684 mStkContext[slotId].mSetupMenuState = STATE_NOT_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001685 return true;
1686 }
Wink Savillee68857d2014-10-17 15:23:05 -07001687 mStkContext[slotId].mSetupMenuState = STATE_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001688 return false;
1689 }
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +05301690
Wink Savillee68857d2014-10-17 15:23:05 -07001691 StkContext getStkContext(int slotId) {
1692 if (slotId >= 0 && slotId < mSimCount) {
1693 return mStkContext[slotId];
1694 } else {
1695 CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
1696 return null;
1697 }
1698 }
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +05301699
1700 private void handleAlphaNotify(Bundle args) {
1701 String alphaString = args.getString(AppInterface.ALPHA_STRING);
1702
1703 CatLog.d(this, "Alpha string received from card: " + alphaString);
1704 Toast toast = Toast.makeText(sInstance, alphaString, Toast.LENGTH_LONG);
1705 toast.setGravity(Gravity.TOP, 0, 0);
1706 toast.show();
1707 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001708}