blob: 3b7f0a59a6205598fb01af08113637f53cd6e4fe [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;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080078
79import java.util.LinkedList;
Wink Savillee68857d2014-10-17 15:23:05 -070080import java.lang.System;
81import java.util.List;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080082
Preeti Ahuja95919342013-10-01 18:18:55 -070083import static com.android.internal.telephony.cat.CatCmdMessage.
Preeti Ahuja560be362014-11-25 19:38:24 -080084 SetupEventListConstants.IDLE_SCREEN_AVAILABLE_EVENT;
85import static com.android.internal.telephony.cat.CatCmdMessage.
Preeti Ahuja95919342013-10-01 18:18:55 -070086 SetupEventListConstants.LANGUAGE_SELECTION_EVENT;
87
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080088/**
89 * SIM toolkit application level service. Interacts with Telephopny messages,
90 * application's launch and user input from STK UI elements.
Wink Saville79085fc2009-06-09 10:27:23 -070091 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080092 */
93public class StkAppService extends Service implements Runnable {
94
95 // members
Wink Savillee68857d2014-10-17 15:23:05 -070096 protected class StkContext {
97 protected CatCmdMessage mMainCmd = null;
98 protected CatCmdMessage mCurrentCmd = null;
99 protected CatCmdMessage mCurrentMenuCmd = null;
100 protected Menu mCurrentMenu = null;
101 protected String lastSelectedItem = null;
102 protected boolean mMenuIsVisible = false;
103 protected boolean mIsInputPending = false;
104 protected boolean mIsMenuPending = false;
105 protected boolean mIsDialogPending = false;
106 protected boolean responseNeeded = true;
107 protected boolean launchBrowser = false;
108 protected BrowserSettings mBrowserSettings = null;
109 protected LinkedList<DelayedCmd> mCmdsQ = null;
110 protected boolean mCmdInProgress = false;
111 protected int mStkServiceState = STATE_UNKNOWN;
112 protected int mSetupMenuState = STATE_UNKNOWN;
113 protected int mMenuState = StkMenuActivity.STATE_INIT;
114 protected int mOpCode = -1;
115 private Activity mActivityInstance = null;
116 private Activity mDialogInstance = null;
117 private Activity mMainActivityInstance = null;
118 private boolean mBackGroundTRSent = false;
119 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);
267 if (null != UiccController.getInstance() && null != UiccController.getInstance()
268 .getUiccCard(i)) {
269 mStkService[i] = UiccController.getInstance().getUiccCard(i).getCatService();
270 } else {
271 CatLog.d(LOG_TAG, "Null instance: [" + UiccController.getInstance() + "],[" +
272 UiccController.getInstance().getUiccCard(i) + "]");
273 }
274 mStkContext[i] = new StkContext();
275 mStkContext[i].mSlotId = i;
276 mStkContext[i].mCmdsQ = new LinkedList<DelayedCmd>();
277 }
278
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800279 Thread serviceThread = new Thread(null, this, "Stk App Service");
280 serviceThread.start();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800281 mNotificationManager = (NotificationManager) mContext
282 .getSystemService(Context.NOTIFICATION_SERVICE);
283 sInstance = this;
284 }
285
286 @Override
287 public void onStart(Intent intent, int startId) {
Wink Savillee68857d2014-10-17 15:23:05 -0700288 if (intent == null) {
289 CatLog.d(LOG_TAG, "StkAppService onStart intent is null so return");
Banavathu, Srinivas Naik87cda962012-07-17 15:32:44 +0530290 return;
291 }
292
Wink Savillee68857d2014-10-17 15:23:05 -0700293 Bundle args = intent.getExtras();
294 if (args == null) {
295 CatLog.d(LOG_TAG, "StkAppService onStart args is null so return");
296 return;
297 }
298
299 int op = args.getInt(OPCODE);
300 int slotId = 0;
301 int i = 0;
302 if (op != OP_BOOT_COMPLETED) {
303 slotId = args.getInt(SLOT_ID);
304 }
305 CatLog.d(LOG_TAG, "onStart sim id: " + slotId + ", op: " + op + ", " + args);
306 if ((slotId >= 0 && slotId < mSimCount) && mStkService[slotId] == null) {
307 if (null != UiccController.getInstance() && null != UiccController.getInstance()
308 .getUiccCard(slotId)) {
309 mStkService[slotId] = UiccController.getInstance().getUiccCard(slotId)
310 .getCatService();
311 } else {
312 CatLog.d(LOG_TAG, "Null instance: [" + UiccController.getInstance() + "],[" +
313 UiccController.getInstance().getUiccCard(slotId)+"]");
314 }
315 if (mStkService[slotId] == null) {
316 CatLog.d(LOG_TAG, "mStkService is: " + mStkContext[slotId].mStkServiceState);
317 mStkContext[slotId].mStkServiceState = STATE_NOT_EXIST;
318 //Check other StkService state.
319 //If all StkServices are not available, stop itself and uninstall apk.
320 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
321 if (i != slotId
322 && (mStkContext[i].mStkServiceState == STATE_UNKNOWN
323 || mStkContext[i].mStkServiceState == STATE_EXIST)) {
324 break;
325 }
326 }
327 } else {
328 mStkContext[slotId].mStkServiceState = STATE_EXIST;
329 }
330 if (i == mSimCount) {
331 stopSelf();
332 StkAppInstaller.unInstall(mContext);
333 return;
334 }
335 }
336
Banavathu, Srinivas Naik87cda962012-07-17 15:32:44 +0530337 waitForLooper();
John Wang62acae42009-10-08 11:20:23 -0700338 // onStart() method can be passed a null intent
339 // TODO: replace onStart() with onStartCommand()
340 if (intent == null) {
341 return;
342 }
343
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800344 Message msg = mServiceHandler.obtainMessage();
Wink Savillee68857d2014-10-17 15:23:05 -0700345 msg.arg1 = op;
346 msg.arg2 = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800347 switch(msg.arg1) {
348 case OP_CMD:
349 msg.obj = args.getParcelable(CMD_MSG);
350 break;
351 case OP_RESPONSE:
Wink Saville94e982b2014-07-11 07:38:14 -0700352 case OP_CARD_STATUS_CHANGED:
Preeti Ahuja95919342013-10-01 18:18:55 -0700353 case OP_LOCALE_CHANGED:
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +0530354 case OP_ALPHA_NOTIFY:
Preeti Ahuja560be362014-11-25 19:38:24 -0800355 case OP_IDLE_SCREEN:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800356 msg.obj = args;
357 /* falls through */
358 case OP_LAUNCH_APP:
359 case OP_END_SESSION:
360 case OP_BOOT_COMPLETED:
361 break;
362 default:
363 return;
364 }
365 mServiceHandler.sendMessage(msg);
366 }
367
368 @Override
369 public void onDestroy() {
Wink Savillee68857d2014-10-17 15:23:05 -0700370 CatLog.d(LOG_TAG, "onDestroy()");
Preeti Ahuja560be362014-11-25 19:38:24 -0800371 if (mStkCmdReceiver != null) {
372 unregisterReceiver(mStkCmdReceiver);
373 mStkCmdReceiver = null;
374 }
375 mPowerManager = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800376 waitForLooper();
377 mServiceLooper.quit();
378 }
379
380 @Override
381 public IBinder onBind(Intent intent) {
382 return null;
383 }
384
385 public void run() {
386 Looper.prepare();
387
388 mServiceLooper = Looper.myLooper();
389 mServiceHandler = new ServiceHandler();
390
391 Looper.loop();
392 }
393
394 /*
395 * Package api used by StkMenuActivity to indicate if its on the foreground.
396 */
Wink Savillee68857d2014-10-17 15:23:05 -0700397 void indicateMenuVisibility(boolean visibility, int slotId) {
398 if (slotId >= 0 && slotId < mSimCount) {
399 mStkContext[slotId].mMenuIsVisible = visibility;
400 }
401 }
402
Preeti Ahuja95919342013-10-01 18:18:55 -0700403 /*
404 * Package api used by StkDialogActivity to indicate if its on the foreground.
405 */
406 void setDisplayTextDlgVisibility(boolean visibility, int slotId) {
407 if (slotId >= 0 && slotId < mSimCount) {
408 mStkContext[slotId].mDisplayTextDlgIsVisibile = visibility;
409 }
410 }
411
Wink Savillee68857d2014-10-17 15:23:05 -0700412 boolean isInputPending(int slotId) {
413 if (slotId >= 0 && slotId < mSimCount) {
414 CatLog.d(LOG_TAG, "isInputFinishBySrv: " + mStkContext[slotId].mIsInputPending);
415 return mStkContext[slotId].mIsInputPending;
416 }
417 return false;
418 }
419
420 boolean isMenuPending(int slotId) {
421 if (slotId >= 0 && slotId < mSimCount) {
422 CatLog.d(LOG_TAG, "isMenuPending: " + mStkContext[slotId].mIsMenuPending);
423 return mStkContext[slotId].mIsMenuPending;
424 }
425 return false;
426 }
427
428 boolean isDialogPending(int slotId) {
429 if (slotId >= 0 && slotId < mSimCount) {
430 CatLog.d(LOG_TAG, "isDialogPending: " + mStkContext[slotId].mIsDialogPending);
431 return mStkContext[slotId].mIsDialogPending;
432 }
433 return false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800434 }
435
436 /*
437 * Package api used by StkMenuActivity to get its Menu parameter.
438 */
Wink Savillee68857d2014-10-17 15:23:05 -0700439 Menu getMenu(int slotId) {
440 CatLog.d(LOG_TAG, "StkAppService, getMenu, sim id: " + slotId);
441 if (slotId >=0 && slotId < mSimCount) {
442 return mStkContext[slotId].mCurrentMenu;
443 } else {
444 return null;
445 }
446 }
447
448 /*
449 * Package api used by StkMenuActivity to get its Main Menu parameter.
450 */
451 Menu getMainMenu(int slotId) {
452 CatLog.d(LOG_TAG, "StkAppService, getMainMenu, sim id: " + slotId);
453 if (slotId >=0 && slotId < mSimCount) {
454 return mStkContext[slotId].mMainCmd.getMenu();
455 } else {
456 return null;
457 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800458 }
459
460 /*
461 * Package api used by UI Activities and Dialogs to communicate directly
462 * with the service to deliver state information and parameters.
463 */
464 static StkAppService getInstance() {
465 return sInstance;
466 }
467
468 private void waitForLooper() {
469 while (mServiceHandler == null) {
470 synchronized (this) {
471 try {
472 wait(100);
473 } catch (InterruptedException e) {
474 }
475 }
476 }
477 }
478
479 private final class ServiceHandler extends Handler {
480 @Override
481 public void handleMessage(Message msg) {
Wink Savillee68857d2014-10-17 15:23:05 -0700482 if(null == msg) {
483 CatLog.d(LOG_TAG, "ServiceHandler handleMessage msg is null");
484 return;
485 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800486 int opcode = msg.arg1;
Wink Savillee68857d2014-10-17 15:23:05 -0700487 int slotId = msg.arg2;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800488
Wink Savillee68857d2014-10-17 15:23:05 -0700489 CatLog.d(LOG_TAG, "handleMessage opcode[" + opcode + "], sim id[" + slotId + "]");
490 if (opcode == OP_CMD && msg.obj != null &&
491 ((CatCmdMessage)msg.obj).getCmdType()!= null) {
492 CatLog.d(LOG_TAG, "cmdName[" + ((CatCmdMessage)msg.obj).getCmdType().name() + "]");
493 }
494 mStkContext[slotId].mOpCode = opcode;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800495 switch (opcode) {
496 case OP_LAUNCH_APP:
Wink Savillee68857d2014-10-17 15:23:05 -0700497 if (mStkContext[slotId].mMainCmd == null) {
498 CatLog.d(LOG_TAG, "mMainCmd is null");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800499 // nothing todo when no SET UP MENU command didn't arrive.
500 return;
501 }
Wink Savillee68857d2014-10-17 15:23:05 -0700502 CatLog.d(LOG_TAG, "handleMessage OP_LAUNCH_APP - mCmdInProgress[" +
503 mStkContext[slotId].mCmdInProgress + "]");
504
505 //If there is a pending activity for the slot id,
506 //just finish it and create a new one to handle the pending command.
507 cleanUpInstanceStackBySlot(slotId);
508
509 //Clean up all other activities in stack.
510 for (int i = 0; i < mSimCount; i++) {
511 if (i != slotId && mStkContext[i].mCurrentCmd != null) {
512 Activity otherAct = mStkContext[i].getPendingActivityInstance();
513 Activity otherDal = mStkContext[i].getPendingDialogInstance();
514 Activity otherMainMenu = mStkContext[i].getMainActivityInstance();
515 if (otherAct != null) {
516 CatLog.d(LOG_TAG, "finish pending otherAct and send SE. slot: " + i);
517 // Send end session for the pending proactive command of slot i in
518 // onDestroy of the activity.
519 // Set mBackGroundTRSent to true for ignoring to show the main menu
520 // for the following end session event.
521 mStkContext[i].mBackGroundTRSent = true;
522 otherAct.finish();
523 mStkContext[i].mActivityInstance = null;
524 }
525 if (otherDal != null) {
526 CatLog.d(LOG_TAG, "finish pending otherDal and send TR for the dialog");
527 mStkContext[i].mBackGroundTRSent = true;
528 otherDal.finish();
529 mStkContext[i].mDialogInstance = null;
530 }
531 if (otherMainMenu != null) {
532 CatLog.d(LOG_TAG, "finish pending otherMainMenu.");
533 otherMainMenu.finish();
534 mStkContext[i].mMainActivityInstance = null;
535 }
536 }
537 }
538 CatLog.d(LOG_TAG, "Current cmd type: " +
539 mStkContext[slotId].mCurrentCmd.getCmdType());
540 //Restore the last command from stack by slot id.
541 restoreInstanceFromStackBySlot(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800542 break;
543 case OP_CMD:
Wink Savillee68857d2014-10-17 15:23:05 -0700544 CatLog.d(LOG_TAG, "[OP_CMD]");
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700545 CatCmdMessage cmdMsg = (CatCmdMessage) msg.obj;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800546 // There are two types of commands:
547 // 1. Interactive - user's response is required.
548 // 2. Informative - display a message, no interaction with the user.
549 //
Wink Saville79085fc2009-06-09 10:27:23 -0700550 // Informative commands can be handled immediately without any delay.
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800551 // Interactive commands can't override each other. So if a command
552 // is already in progress, we need to queue the next command until
553 // the user has responded or a timeout expired.
554 if (!isCmdInteractive(cmdMsg)) {
Wink Savillee68857d2014-10-17 15:23:05 -0700555 handleCmd(cmdMsg, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800556 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700557 if (!mStkContext[slotId].mCmdInProgress) {
558 mStkContext[slotId].mCmdInProgress = true;
559 handleCmd((CatCmdMessage) msg.obj, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800560 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700561 CatLog.d(LOG_TAG, "[Interactive][in progress]");
562 mStkContext[slotId].mCmdsQ.addLast(new DelayedCmd(OP_CMD,
563 (CatCmdMessage) msg.obj, slotId));
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800564 }
565 }
566 break;
567 case OP_RESPONSE:
Preeti Ahuja414bc412013-06-25 19:31:49 -0700568 handleCmdResponse((Bundle) msg.obj, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800569 // call delayed commands if needed.
Wink Savillee68857d2014-10-17 15:23:05 -0700570 if (mStkContext[slotId].mCmdsQ.size() != 0) {
571 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800572 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700573 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800574 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800575 break;
576 case OP_END_SESSION:
Wink Savillee68857d2014-10-17 15:23:05 -0700577 if (!mStkContext[slotId].mCmdInProgress) {
578 mStkContext[slotId].mCmdInProgress = true;
579 handleSessionEnd(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800580 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700581 mStkContext[slotId].mCmdsQ.addLast(
582 new DelayedCmd(OP_END_SESSION, null, slotId));
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800583 }
584 break;
585 case OP_BOOT_COMPLETED:
Wink Savillee68857d2014-10-17 15:23:05 -0700586 CatLog.d(LOG_TAG, " OP_BOOT_COMPLETED");
587 int i = 0;
588 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
589 if (mStkContext[i].mMainCmd != null) {
590 break;
591 }
592 }
593 if (i == mSimCount) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800594 StkAppInstaller.unInstall(mContext);
595 }
596 break;
597 case OP_DELAYED_MSG:
Wink Savillee68857d2014-10-17 15:23:05 -0700598 handleDelayedCmd(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800599 break;
Wink Saville94e982b2014-07-11 07:38:14 -0700600 case OP_CARD_STATUS_CHANGED:
Wink Savillee68857d2014-10-17 15:23:05 -0700601 CatLog.d(LOG_TAG, "Card/Icc Status change received");
602 handleCardStatusChangeAndIccRefresh((Bundle) msg.obj, slotId);
603 break;
604 case OP_SET_ACT_INST:
605 Activity act = new Activity();
606 act = (Activity) msg.obj;
607 CatLog.d(LOG_TAG, "Set activity instance. " + act);
608 mStkContext[slotId].mActivityInstance = act;
609 break;
610 case OP_SET_DAL_INST:
611 Activity dal = new Activity();
612 CatLog.d(LOG_TAG, "Set dialog instance. " + dal);
613 dal = (Activity) msg.obj;
614 mStkContext[slotId].mDialogInstance = dal;
615 break;
616 case OP_SET_MAINACT_INST:
617 Activity mainAct = new Activity();
618 mainAct = (Activity) msg.obj;
619 CatLog.d(LOG_TAG, "Set activity instance. " + mainAct);
620 mStkContext[slotId].mMainActivityInstance = mainAct;
Wink Saville94e982b2014-07-11 07:38:14 -0700621 break;
Preeti Ahuja95919342013-10-01 18:18:55 -0700622 case OP_LOCALE_CHANGED:
623 CatLog.d(this, "Locale Changed");
624 checkForSetupEvent(LANGUAGE_SELECTION_EVENT,(Bundle) msg.obj, slotId);
625 break;
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +0530626 case OP_ALPHA_NOTIFY:
627 handleAlphaNotify((Bundle) msg.obj);
628 break;
Preeti Ahuja560be362014-11-25 19:38:24 -0800629 case OP_IDLE_SCREEN:
630 for (int slot = 0; slot < mSimCount; slot++) {
631 if (mStkContext[slot] != null) {
632 handleIdleScreen(slot);
633 }
634 }
635 break;
Wink Saville94e982b2014-07-11 07:38:14 -0700636 }
637 }
638
Wink Savillee68857d2014-10-17 15:23:05 -0700639 private void handleCardStatusChangeAndIccRefresh(Bundle args, int slotId) {
Wink Saville94e982b2014-07-11 07:38:14 -0700640 boolean cardStatus = args.getBoolean(AppInterface.CARD_STATUS);
641
Wink Savillee68857d2014-10-17 15:23:05 -0700642 CatLog.d(LOG_TAG, "CardStatus: " + cardStatus);
Wink Saville94e982b2014-07-11 07:38:14 -0700643 if (cardStatus == false) {
Wink Savillee68857d2014-10-17 15:23:05 -0700644 CatLog.d(LOG_TAG, "CARD is ABSENT");
Wink Saville94e982b2014-07-11 07:38:14 -0700645 // Uninstall STKAPP, Clear Idle text, Stop StkAppService
Wink Savillee68857d2014-10-17 15:23:05 -0700646 mNotificationManager.cancel(getNotificationId(slotId));
647 if (isAllOtherCardsAbsent(slotId)) {
648 CatLog.d(LOG_TAG, "All CARDs are ABSENT");
649 StkAppInstaller.unInstall(mContext);
650 stopSelf();
651 }
Wink Saville94e982b2014-07-11 07:38:14 -0700652 } else {
653 IccRefreshResponse state = new IccRefreshResponse();
654 state.refreshResult = args.getInt(AppInterface.REFRESH_RESULT);
655
Wink Savillee68857d2014-10-17 15:23:05 -0700656 CatLog.d(LOG_TAG, "Icc Refresh Result: "+ state.refreshResult);
Wink Saville94e982b2014-07-11 07:38:14 -0700657 if ((state.refreshResult == IccRefreshResponse.REFRESH_RESULT_INIT) ||
658 (state.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET)) {
659 // Clear Idle Text
Wink Savillee68857d2014-10-17 15:23:05 -0700660 mNotificationManager.cancel(getNotificationId(slotId));
Wink Saville94e982b2014-07-11 07:38:14 -0700661 }
662
663 if (state.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET) {
664 // Uninstall STkmenu
Wink Savillee68857d2014-10-17 15:23:05 -0700665 if (isAllOtherCardsAbsent(slotId)) {
666 StkAppInstaller.unInstall(mContext);
667 }
668 mStkContext[slotId].mCurrentMenu = null;
669 mStkContext[slotId].mMainCmd = null;
Wink Saville94e982b2014-07-11 07:38:14 -0700670 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800671 }
672 }
673 }
Wink Savillee68857d2014-10-17 15:23:05 -0700674 /*
675 * Check if all SIMs are absent except the id of slot equals "slotId".
676 */
677 private boolean isAllOtherCardsAbsent(int slotId) {
678 TelephonyManager mTm = (TelephonyManager) mContext.getSystemService(
679 Context.TELEPHONY_SERVICE);
680 int i = 0;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800681
Wink Savillee68857d2014-10-17 15:23:05 -0700682 for (i = 0; i < mSimCount; i++) {
683 if (i != slotId && mTm.hasIccCard(i)) {
684 break;
685 }
686 }
687 if (i == mSimCount) {
688 return true;
689 } else {
690 return false;
691 }
692 }
Preeti Ahuja95919342013-10-01 18:18:55 -0700693
Preeti Ahuja560be362014-11-25 19:38:24 -0800694 /*
695 * If the device is not in an interactive state, we can assume
696 * that the screen is idle.
697 */
698 private boolean isScreenIdle() {
699 return (!mPowerManager.isInteractive());
700 }
701
702 private void handleIdleScreen(int slotId) {
703
704 // If the idle screen event is present in the list need to send the
705 // response to SIM.
706 CatLog.d(this, "Need to send IDLE SCREEN Available event to SIM");
707 checkForSetupEvent(IDLE_SCREEN_AVAILABLE_EVENT, null, slotId);
708
709 if (mStkContext[slotId].mIdleModeTextCmd != null) {
710 launchIdleText(slotId);
711 }
712 }
713
714 private void sendScreenBusyResponse(int slotId) {
715 if (mStkContext[slotId].mCurrentCmd == null) {
716 return;
717 }
718 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentCmd);
719 CatLog.d(this, "SCREEN_BUSY");
720 resMsg.setResultCode(ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS);
721 mStkService[slotId].onCmdResponse(resMsg);
722 if (mStkContext[slotId].mCmdsQ.size() != 0) {
723 callDelayedMsg(slotId);
724 } else {
725 mStkContext[slotId].mCmdInProgress = false;
726 }
727 }
728
Preeti Ahuja95919342013-10-01 18:18:55 -0700729 private void sendResponse(int resId, int slotId, boolean confirm) {
730 Message msg = mServiceHandler.obtainMessage();
731 msg.arg1 = OP_RESPONSE;
732 Bundle args = new Bundle();
733 args.putInt(StkAppService.RES_ID, resId);
734 args.putInt(SLOT_ID, slotId);
735 args.putBoolean(StkAppService.CONFIRMATION, confirm);
736 msg.obj = args;
737 mServiceHandler.sendMessage(msg);
738 }
739
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700740 private boolean isCmdInteractive(CatCmdMessage cmd) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800741 switch (cmd.getCmdType()) {
742 case SEND_DTMF:
743 case SEND_SMS:
744 case SEND_SS:
745 case SEND_USSD:
746 case SET_UP_IDLE_MODE_TEXT:
747 case SET_UP_MENU:
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500748 case CLOSE_CHANNEL:
749 case RECEIVE_DATA:
750 case SEND_DATA:
Preeti Ahuja95919342013-10-01 18:18:55 -0700751 case SET_UP_EVENT_LIST:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800752 return false;
753 }
754
755 return true;
756 }
757
Wink Savillee68857d2014-10-17 15:23:05 -0700758 private void handleDelayedCmd(int slotId) {
759 CatLog.d(LOG_TAG, "handleDelayedCmd, slotId: " + slotId);
760 if (mStkContext[slotId].mCmdsQ.size() != 0) {
761 DelayedCmd cmd = mStkContext[slotId].mCmdsQ.poll();
762 if (cmd != null) {
763 CatLog.d(LOG_TAG, "handleDelayedCmd - queue size: " +
764 mStkContext[slotId].mCmdsQ.size() +
765 " id: " + cmd.id + "sim id: " + cmd.slotId);
766 switch (cmd.id) {
767 case OP_CMD:
768 handleCmd(cmd.msg, cmd.slotId);
769 break;
770 case OP_END_SESSION:
771 handleSessionEnd(cmd.slotId);
772 break;
773 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800774 }
775 }
776 }
777
Wink Savillee68857d2014-10-17 15:23:05 -0700778 private void callDelayedMsg(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800779 Message msg = mServiceHandler.obtainMessage();
780 msg.arg1 = OP_DELAYED_MSG;
Wink Savillee68857d2014-10-17 15:23:05 -0700781 msg.arg2 = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800782 mServiceHandler.sendMessage(msg);
783 }
784
Wink Savillee68857d2014-10-17 15:23:05 -0700785 private void callSetActivityInstMsg(int inst_type, int slotId, Object obj) {
786 Message msg = mServiceHandler.obtainMessage();
787 msg.obj = obj;
788 msg.arg1 = inst_type;
789 msg.arg2 = slotId;
790 mServiceHandler.sendMessage(msg);
791 }
792
793 private void handleSessionEnd(int slotId) {
794 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
795 CatLog.d(LOG_TAG, "[handleSessionEnd] - mCurrentCmd changed to mMainCmd!.");
796 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mMainCmd;
797 CatLog.d(LOG_TAG, "slotId: " + slotId + ", mMenuState: " +
798 mStkContext[slotId].mMenuState);
799
800 mStkContext[slotId].mIsInputPending = false;
801 mStkContext[slotId].mIsMenuPending = false;
802 mStkContext[slotId].mIsDialogPending = false;
803
804 // We should finish all pending activity if receiving END SESSION command.
805 cleanUpInstanceStackBySlot(slotId);
806
807 if (mStkContext[slotId].mMainCmd == null) {
808 CatLog.d(LOG_TAG, "[handleSessionEnd][mMainCmd is null!]");
809 }
810 mStkContext[slotId].lastSelectedItem = null;
Wink Saville79085fc2009-06-09 10:27:23 -0700811 // In case of SET UP MENU command which removed the app, don't
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800812 // update the current menu member.
Wink Savillee68857d2014-10-17 15:23:05 -0700813 if (mStkContext[slotId].mCurrentMenu != null && mStkContext[slotId].mMainCmd != null) {
814 mStkContext[slotId].mCurrentMenu = mStkContext[slotId].mMainCmd.getMenu();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800815 }
Wink Savillee68857d2014-10-17 15:23:05 -0700816 CatLog.d(LOG_TAG, "[handleSessionEnd][mMenuState]" + mStkContext[slotId].mMenuIsVisible);
817 // In mutiple instance architecture, the main menu for slotId will be finished when user
818 // goes to the Stk menu of the other SIM. So, we should launch a new instance for the
819 // main menu if the main menu instance has been finished.
820 // If the current menu is secondary menu, we should launch main menu.
821 if (StkMenuActivity.STATE_SECONDARY == mStkContext[slotId].mMenuState) {
822 launchMenuActivity(null, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800823 }
Wink Savillee68857d2014-10-17 15:23:05 -0700824 if (mStkContext[slotId].mCmdsQ.size() != 0) {
825 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800826 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700827 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800828 }
829 // In case a launch browser command was just confirmed, launch that url.
Wink Savillee68857d2014-10-17 15:23:05 -0700830 if (mStkContext[slotId].launchBrowser) {
831 mStkContext[slotId].launchBrowser = false;
832 launchBrowser(mStkContext[slotId].mBrowserSettings);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800833 }
834 }
835
Preeti Ahuja560be362014-11-25 19:38:24 -0800836 // returns true if any Stk related activity already has focus on the screen
837 private boolean isTopOfStack() {
838 ActivityManager mAcivityManager = (ActivityManager) mContext
839 .getSystemService(ACTIVITY_SERVICE);
840 String currentPackageName = mAcivityManager.getRunningTasks(1).get(0).topActivity
841 .getPackageName();
842 if (null != currentPackageName) {
843 return currentPackageName.equals(PACKAGE_NAME);
844 }
845
846 return false;
847 }
848
Wink Savillee68857d2014-10-17 15:23:05 -0700849 private void handleCmd(CatCmdMessage cmdMsg, int slotId) {
Preeti Ahuja95919342013-10-01 18:18:55 -0700850
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800851 if (cmdMsg == null) {
852 return;
853 }
854 // save local reference for state tracking.
Wink Savillee68857d2014-10-17 15:23:05 -0700855 mStkContext[slotId].mCurrentCmd = cmdMsg;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800856 boolean waitForUsersResponse = true;
857
Wink Savillee68857d2014-10-17 15:23:05 -0700858 mStkContext[slotId].mIsInputPending = false;
859 mStkContext[slotId].mIsMenuPending = false;
860 mStkContext[slotId].mIsDialogPending = false;
861
862 CatLog.d(LOG_TAG,"[handleCmd]" + cmdMsg.getCmdType().name());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800863 switch (cmdMsg.getCmdType()) {
864 case DISPLAY_TEXT:
865 TextMessage msg = cmdMsg.geTextMessage();
Jeevaka Badrappan854a25c2012-12-01 16:32:03 +0200866 waitForUsersResponse = msg.responseNeeded;
Wink Savillee68857d2014-10-17 15:23:05 -0700867 if (mStkContext[slotId].lastSelectedItem != null) {
868 msg.title = mStkContext[slotId].lastSelectedItem;
869 } else if (mStkContext[slotId].mMainCmd != null){
870 msg.title = mStkContext[slotId].mMainCmd.getMenu().title;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800871 } else {
872 // TODO: get the carrier name from the SIM
873 msg.title = "";
874 }
Preeti Ahuja560be362014-11-25 19:38:24 -0800875 //If we receive a low priority Display Text and the device is
876 // not displaying any STK related activity and the screen is not idle
877 // ( that is, device is in an interactive state), then send a screen busy
878 // terminal response. Otherwise display the message. The existing
879 // displayed message shall be updated with the new display text
880 // proactive command (Refer to ETSI TS 102 384 section 27.22.4.1.4.4.2).
881 if (!(msg.isHighPriority || mStkContext[slotId].mMenuIsVisible
882 || mStkContext[slotId].mDisplayTextDlgIsVisibile || isTopOfStack())) {
883 if(!isScreenIdle()) {
884 CatLog.d(LOG_TAG, "Screen is not idle");
885 sendScreenBusyResponse(slotId);
886 } else {
887 launchTextDialog(slotId);
888 }
889 } else {
890 launchTextDialog(slotId);
891 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800892 break;
893 case SELECT_ITEM:
Wink Savillee68857d2014-10-17 15:23:05 -0700894 CatLog.d(LOG_TAG, "SELECT_ITEM +");
895 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
896 mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
897 launchMenuActivity(cmdMsg.getMenu(), slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800898 break;
899 case SET_UP_MENU:
Wink Savillee68857d2014-10-17 15:23:05 -0700900 mStkContext[slotId].mCmdInProgress = false;
901 mStkContext[slotId].mMainCmd = mStkContext[slotId].mCurrentCmd;
902 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
903 mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
904 CatLog.d(LOG_TAG, "SET_UP_MENU [" + removeMenu(slotId) + "]");
905
906 if (removeMenu(slotId)) {
907 int i = 0;
908 CatLog.d(LOG_TAG, "removeMenu() - Uninstall App");
909 mStkContext[slotId].mCurrentMenu = null;
Preeti Ahuja95919342013-10-01 18:18:55 -0700910 mStkContext[slotId].mMainCmd = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700911 //Check other setup menu state. If all setup menu are removed, uninstall apk.
912 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
913 if (i != slotId
914 && (mStkContext[slotId].mSetupMenuState == STATE_UNKNOWN
915 || mStkContext[slotId].mSetupMenuState == STATE_EXIST)) {
916 CatLog.d(LOG_TAG, "Not Uninstall App:" + i + ","
917 + mStkContext[slotId].mSetupMenuState);
918 break;
919 }
920 }
921 if (i == mSimCount) {
922 StkAppInstaller.unInstall(mContext);
923 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800924 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700925 CatLog.d(LOG_TAG, "install App");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800926 StkAppInstaller.install(mContext);
927 }
Wink Savillee68857d2014-10-17 15:23:05 -0700928 if (mStkContext[slotId].mMenuIsVisible) {
929 launchMenuActivity(null, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800930 }
931 break;
932 case GET_INPUT:
933 case GET_INKEY:
Wink Savillee68857d2014-10-17 15:23:05 -0700934 launchInputActivity(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800935 break;
936 case SET_UP_IDLE_MODE_TEXT:
937 waitForUsersResponse = false;
Preeti Ahuja560be362014-11-25 19:38:24 -0800938 mStkContext[slotId].mIdleModeTextCmd = mStkContext[slotId].mCurrentCmd;
939 TextMessage idleModeText = mStkContext[slotId].mCurrentCmd.geTextMessage();
940 if (idleModeText == null) {
941 launchIdleText(slotId);
942 mStkContext[slotId].mIdleModeTextCmd = null;
943 }
944 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
945 if ((mStkContext[slotId].mIdleModeTextCmd != null) && isScreenIdle()) {
946 CatLog.d(this, "set up idle mode");
947 launchIdleText(slotId);
948 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800949 break;
950 case SEND_DTMF:
951 case SEND_SMS:
952 case SEND_SS:
953 case SEND_USSD:
Preeti Ahuja95919342013-10-01 18:18:55 -0700954 case GET_CHANNEL_STATUS:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800955 waitForUsersResponse = false;
Wink Savillee68857d2014-10-17 15:23:05 -0700956 launchEventMessage(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800957 break;
958 case LAUNCH_BROWSER:
Wink Savillee68857d2014-10-17 15:23:05 -0700959 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.geTextMessage(), slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800960 break;
961 case SET_UP_CALL:
Preeti Ahujadd240102013-08-30 17:25:06 -0700962 TextMessage mesg = mStkContext[slotId].mCurrentCmd.getCallSettings().confirmMsg;
963 if((mesg != null) && (mesg.text == null || mesg.text.length() == 0)) {
964 mesg.text = getResources().getString(R.string.default_setup_call_msg);
965 }
966 CatLog.d(this, "SET_UP_CALL mesg.text " + mesg.text);
967 launchConfirmationDialog(mesg, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800968 break;
969 case PLAY_TONE:
Wink Savillee68857d2014-10-17 15:23:05 -0700970 launchToneDialog(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800971 break;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500972 case OPEN_CHANNEL:
Wink Savillee68857d2014-10-17 15:23:05 -0700973 launchOpenChannelDialog(slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500974 break;
975 case CLOSE_CHANNEL:
976 case RECEIVE_DATA:
977 case SEND_DATA:
Wink Savillee68857d2014-10-17 15:23:05 -0700978 TextMessage m = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500979
980 if ((m != null) && (m.text == null)) {
981 switch(cmdMsg.getCmdType()) {
982 case CLOSE_CHANNEL:
983 m.text = getResources().getString(R.string.default_close_channel_msg);
984 break;
985 case RECEIVE_DATA:
986 m.text = getResources().getString(R.string.default_receive_data_msg);
987 break;
988 case SEND_DATA:
989 m.text = getResources().getString(R.string.default_send_data_msg);
990 break;
991 }
992 }
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -0700993 /*
994 * Display indication in the form of a toast to the user if required.
995 */
Wink Savillee68857d2014-10-17 15:23:05 -0700996 launchEventMessage(slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500997 break;
Preeti Ahuja95919342013-10-01 18:18:55 -0700998 case SET_UP_EVENT_LIST:
999 mStkContext[slotId].mSetupEventListSettings =
1000 mStkContext[slotId].mCurrentCmd.getSetEventList();
1001 mStkContext[slotId].mCurrentSetupEventCmd = mStkContext[slotId].mCurrentCmd;
1002 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
Preeti Ahuja560be362014-11-25 19:38:24 -08001003 if (isScreenIdle()) {
1004 CatLog.d(this," Check if IDLE_SCREEN_AVAILABLE_EVENT is present in List");
1005 checkForSetupEvent(IDLE_SCREEN_AVAILABLE_EVENT, null, slotId);
1006 }
Preeti Ahuja95919342013-10-01 18:18:55 -07001007 break;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001008 }
1009
1010 if (!waitForUsersResponse) {
Wink Savillee68857d2014-10-17 15:23:05 -07001011 if (mStkContext[slotId].mCmdsQ.size() != 0) {
1012 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001013 } else {
Wink Savillee68857d2014-10-17 15:23:05 -07001014 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001015 }
1016 }
1017 }
1018
Wink Savillee68857d2014-10-17 15:23:05 -07001019 private void handleCmdResponse(Bundle args, int slotId) {
1020 CatLog.d(LOG_TAG, "handleCmdResponse, sim id: " + slotId);
1021 if (mStkContext[slotId].mCurrentCmd == null) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001022 return;
1023 }
Wink Savillee68857d2014-10-17 15:23:05 -07001024
1025 if (mStkService[slotId] == null) {
1026 if(null != UiccController.getInstance() &&
1027 null != UiccController.getInstance().getUiccCard(slotId)) {
1028 mStkService[slotId] = UiccController.getInstance().getUiccCard(slotId)
1029 .getCatService();
1030 } else {
1031 CatLog.d(LOG_TAG, "Null instance: [" + UiccController.getInstance() +
1032 "],["+UiccController.getInstance().getUiccCard(slotId)+"]");
1033 }
1034 if (mStkService[slotId] == null) {
Alex Yakavenkad8e2ecd2012-04-20 17:10:15 -07001035 // This should never happen (we should be responding only to a message
1036 // that arrived from StkService). It has to exist by this time
Wink Savillee68857d2014-10-17 15:23:05 -07001037 CatLog.d(LOG_TAG, "Exception! mStkService is null when we need to send response.");
Alex Yakavenkad8e2ecd2012-04-20 17:10:15 -07001038 throw new RuntimeException("mStkService is null when we need to send response");
1039 }
1040 }
1041
Wink Savillee68857d2014-10-17 15:23:05 -07001042 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentCmd);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001043
1044 // set result code
1045 boolean helpRequired = args.getBoolean(HELP, false);
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001046 boolean confirmed = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001047
1048 switch(args.getInt(RES_ID)) {
1049 case RES_ID_MENU_SELECTION:
Wink Savillee68857d2014-10-17 15:23:05 -07001050 CatLog.d(LOG_TAG, "MENU_SELECTION=" + mStkContext[slotId].
1051 mCurrentMenuCmd.getCmdType());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001052 int menuSelection = args.getInt(MENU_SELECTION);
Wink Savillee68857d2014-10-17 15:23:05 -07001053 switch(mStkContext[slotId].mCurrentMenuCmd.getCmdType()) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001054 case SET_UP_MENU:
1055 case SELECT_ITEM:
Wink Savillee68857d2014-10-17 15:23:05 -07001056 mStkContext[slotId].lastSelectedItem = getItemName(menuSelection, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001057 if (helpRequired) {
1058 resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
1059 } else {
1060 resMsg.setResultCode(ResultCode.OK);
1061 }
1062 resMsg.setMenuSelection(menuSelection);
1063 break;
1064 }
1065 break;
1066 case RES_ID_INPUT:
Wink Savillee68857d2014-10-17 15:23:05 -07001067 CatLog.d(LOG_TAG, "RES_ID_INPUT");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001068 String input = args.getString(INPUT);
Wink Savillee68857d2014-10-17 15:23:05 -07001069 if (input != null && (null != mStkContext[slotId].mCurrentCmd.geInput()) &&
1070 (mStkContext[slotId].mCurrentCmd.geInput().yesNo)) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001071 boolean yesNoSelection = input
1072 .equals(StkInputActivity.YES_STR_RESPONSE);
1073 resMsg.setYesNo(yesNoSelection);
1074 } else {
1075 if (helpRequired) {
1076 resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
1077 } else {
1078 resMsg.setResultCode(ResultCode.OK);
1079 resMsg.setInput(input);
1080 }
1081 }
1082 break;
1083 case RES_ID_CONFIRM:
Alex Yakavenkad41f1d92010-07-12 14:13:13 -07001084 CatLog.d(this, "RES_ID_CONFIRM");
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001085 confirmed = args.getBoolean(CONFIRMATION);
Wink Savillee68857d2014-10-17 15:23:05 -07001086 switch (mStkContext[slotId].mCurrentCmd.getCmdType()) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001087 case DISPLAY_TEXT:
1088 resMsg.setResultCode(confirmed ? ResultCode.OK
Preeti Ahuja95919342013-10-01 18:18:55 -07001089 : ResultCode.UICC_SESSION_TERM_BY_USER);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001090 break;
1091 case LAUNCH_BROWSER:
1092 resMsg.setResultCode(confirmed ? ResultCode.OK
1093 : ResultCode.UICC_SESSION_TERM_BY_USER);
1094 if (confirmed) {
Wink Savillee68857d2014-10-17 15:23:05 -07001095 mStkContext[slotId].launchBrowser = true;
1096 mStkContext[slotId].mBrowserSettings =
1097 mStkContext[slotId].mCurrentCmd.getBrowserSettings();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001098 }
1099 break;
1100 case SET_UP_CALL:
1101 resMsg.setResultCode(ResultCode.OK);
1102 resMsg.setConfirmation(confirmed);
1103 if (confirmed) {
w302345ad585e2014-11-04 12:13:38 -08001104 CatLog.d(this, "Going back to mainMenu before starting a call.");
1105 launchMenuActivity(null, slotId);
Wink Savillee68857d2014-10-17 15:23:05 -07001106 launchEventMessage(slotId,
1107 mStkContext[slotId].mCurrentCmd.getCallSettings().callMsg);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001108 }
1109 break;
1110 }
1111 break;
1112 case RES_ID_DONE:
1113 resMsg.setResultCode(ResultCode.OK);
1114 break;
1115 case RES_ID_BACKWARD:
Wink Savillee68857d2014-10-17 15:23:05 -07001116 CatLog.d(LOG_TAG, "RES_ID_BACKWARD");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001117 resMsg.setResultCode(ResultCode.BACKWARD_MOVE_BY_USER);
1118 break;
1119 case RES_ID_END_SESSION:
Wink Savillee68857d2014-10-17 15:23:05 -07001120 CatLog.d(LOG_TAG, "RES_ID_END_SESSION");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001121 resMsg.setResultCode(ResultCode.UICC_SESSION_TERM_BY_USER);
1122 break;
1123 case RES_ID_TIMEOUT:
Wink Savillee68857d2014-10-17 15:23:05 -07001124 CatLog.d(LOG_TAG, "RES_ID_TIMEOUT");
Naveen Kallad5176892009-11-30 12:45:29 -08001125 // GCF test-case 27.22.4.1.1 Expected Sequence 1.5 (DISPLAY TEXT,
1126 // Clear message after delay, successful) expects result code OK.
1127 // If the command qualifier specifies no user response is required
1128 // then send OK instead of NO_RESPONSE_FROM_USER
Wink Savillee68857d2014-10-17 15:23:05 -07001129 if ((mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1130 AppInterface.CommandType.DISPLAY_TEXT.value())
1131 && (mStkContext[slotId].mCurrentCmd.geTextMessage().userClear == false)) {
Naveen Kallad5176892009-11-30 12:45:29 -08001132 resMsg.setResultCode(ResultCode.OK);
1133 } else {
1134 resMsg.setResultCode(ResultCode.NO_RESPONSE_FROM_USER);
1135 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001136 break;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001137 case RES_ID_CHOICE:
1138 int choice = args.getInt(CHOICE);
1139 CatLog.d(this, "User Choice=" + choice);
1140 switch (choice) {
1141 case YES:
1142 resMsg.setResultCode(ResultCode.OK);
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001143 confirmed = true;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001144 break;
1145 case NO:
1146 resMsg.setResultCode(ResultCode.USER_NOT_ACCEPT);
1147 break;
1148 }
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001149
Wink Savillee68857d2014-10-17 15:23:05 -07001150 if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1151 AppInterface.CommandType.OPEN_CHANNEL.value()) {
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001152 resMsg.setConfirmation(confirmed);
1153 }
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001154 break;
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001155
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001156 default:
Wink Savillee68857d2014-10-17 15:23:05 -07001157 CatLog.d(LOG_TAG, "Unknown result id");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001158 return;
1159 }
Wink Savillee68857d2014-10-17 15:23:05 -07001160
1161 if (null != mStkContext[slotId].mCurrentCmd &&
1162 null != mStkContext[slotId].mCurrentCmd.getCmdType()) {
1163 CatLog.d(LOG_TAG, "handleCmdResponse- cmdName[" +
1164 mStkContext[slotId].mCurrentCmd.getCmdType().name() + "]");
1165 }
1166 mStkService[slotId].onCmdResponse(resMsg);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001167 }
1168
1169 /**
1170 * Returns 0 or FLAG_ACTIVITY_NO_USER_ACTION, 0 means the user initiated the action.
1171 *
1172 * @param userAction If the userAction is yes then we always return 0 otherwise
1173 * mMenuIsVisible is used to determine what to return. If mMenuIsVisible is true
1174 * then we are the foreground app and we'll return 0 as from our perspective a
1175 * user action did cause. If it's false than we aren't the foreground app and
1176 * FLAG_ACTIVITY_NO_USER_ACTION is returned.
Wink Saville79085fc2009-06-09 10:27:23 -07001177 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001178 * @return 0 or FLAG_ACTIVITY_NO_USER_ACTION
1179 */
Wink Savillee68857d2014-10-17 15:23:05 -07001180 private int getFlagActivityNoUserAction(InitiatedByUserAction userAction, int slotId) {
1181 return ((userAction == InitiatedByUserAction.yes) | mStkContext[slotId].mMenuIsVisible)
1182 ? 0 : Intent.FLAG_ACTIVITY_NO_USER_ACTION;
1183 }
1184 /**
1185 * This method is used for cleaning up pending instances in stack.
1186 */
1187 private void cleanUpInstanceStackBySlot(int slotId) {
1188 Activity activity = mStkContext[slotId].getPendingActivityInstance();
1189 Activity dialog = mStkContext[slotId].getPendingDialogInstance();
1190 CatLog.d(LOG_TAG, "cleanUpInstanceStackBySlot slotId: " + slotId);
1191 if (activity != null) {
1192 CatLog.d(LOG_TAG, "current cmd type: " +
1193 mStkContext[slotId].mCurrentCmd.getCmdType());
1194 if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1195 AppInterface.CommandType.GET_INPUT.value() ||
1196 mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1197 AppInterface.CommandType.GET_INKEY.value()) {
1198 mStkContext[slotId].mIsInputPending = true;
1199 } else if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1200 AppInterface.CommandType.SET_UP_MENU.value() ||
1201 mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1202 AppInterface.CommandType.SELECT_ITEM.value()) {
1203 mStkContext[slotId].mIsMenuPending = true;
1204 } else {
1205 }
1206 CatLog.d(LOG_TAG, "finish pending activity.");
1207 activity.finish();
1208 mStkContext[slotId].mActivityInstance = null;
1209 }
1210 if (dialog != null) {
1211 CatLog.d(LOG_TAG, "finish pending dialog.");
1212 mStkContext[slotId].mIsDialogPending = true;
1213 dialog.finish();
1214 mStkContext[slotId].mDialogInstance = null;
1215 }
1216 }
1217 /**
1218 * This method is used for restoring pending instances from stack.
1219 */
1220 private void restoreInstanceFromStackBySlot(int slotId) {
1221 AppInterface.CommandType cmdType = mStkContext[slotId].mCurrentCmd.getCmdType();
1222
1223 CatLog.d(LOG_TAG, "restoreInstanceFromStackBySlot cmdType : " + cmdType);
1224 switch(cmdType) {
1225 case GET_INPUT:
1226 case GET_INKEY:
1227 launchInputActivity(slotId);
1228 //Set mMenuIsVisible to true for showing main menu for
1229 //following session end command.
1230 mStkContext[slotId].mMenuIsVisible = true;
1231 break;
1232 case DISPLAY_TEXT:
1233 launchTextDialog(slotId);
1234 break;
1235 case LAUNCH_BROWSER:
1236 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.geTextMessage(),
1237 slotId);
1238 break;
1239 case OPEN_CHANNEL:
1240 launchOpenChannelDialog(slotId);
1241 break;
1242 case SET_UP_CALL:
1243 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.getCallSettings().
1244 confirmMsg, slotId);
1245 break;
1246 case SET_UP_MENU:
1247 case SELECT_ITEM:
1248 launchMenuActivity(null, slotId);
1249 break;
1250 default:
1251 break;
1252 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001253 }
1254
Wink Savillee68857d2014-10-17 15:23:05 -07001255 private void launchMenuActivity(Menu menu, int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001256 Intent newIntent = new Intent(Intent.ACTION_VIEW);
Wink Savillee68857d2014-10-17 15:23:05 -07001257 String targetActivity = STK_MENU_ACTIVITY_NAME;
1258 String uriString = STK_MENU_URI + System.currentTimeMillis();
1259 //Set unique URI to create a new instance of activity for different slotId.
1260 Uri uriData = Uri.parse(uriString);
1261
1262 CatLog.d(LOG_TAG, "launchMenuActivity, slotId: " + slotId + " , " +
1263 uriData.toString() + " , " + mStkContext[slotId].mOpCode + ", "
1264 + mStkContext[slotId].mMenuState);
1265 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1266 int intentFlags = Intent.FLAG_ACTIVITY_NEW_TASK;
1267
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001268 if (menu == null) {
1269 // We assume this was initiated by the user pressing the tool kit icon
Wink Savillee68857d2014-10-17 15:23:05 -07001270 intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.yes, slotId);
1271 if (mStkContext[slotId].mOpCode == OP_END_SESSION) {
1272 CatLog.d(LOG_TAG, "launchMenuActivity, return OP_END_SESSION");
1273 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
1274 if (mStkContext[slotId].mMainActivityInstance != null) {
1275 CatLog.d(LOG_TAG, "launchMenuActivity, mMainActivityInstance is not null");
1276 return;
1277 }
1278 // If END SESSION is sent that results from the activity is finished by
1279 // stkappservice (line 457), we should igonore to display the stk main menu
1280 // of slot id.
1281 if (mStkContext[slotId].mBackGroundTRSent) {
1282 CatLog.d(LOG_TAG, "launchMenuActivity, ES is triggered by BG.");
1283 mStkContext[slotId].mBackGroundTRSent = false;
1284 return;
1285 }
1286 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001287
Wink Savillee68857d2014-10-17 15:23:05 -07001288 //If the last pending menu is secondary menu, "STATE" should be "STATE_SECONDARY".
1289 //Otherwise, it should be "STATE_MAIN".
1290 if (mStkContext[slotId].mOpCode == OP_LAUNCH_APP &&
1291 mStkContext[slotId].mMenuState == StkMenuActivity.STATE_SECONDARY) {
1292 newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
1293 } else {
1294 newIntent.putExtra("STATE", StkMenuActivity.STATE_MAIN);
1295 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
1296 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001297 } else {
1298 // We don't know and we'll let getFlagActivityNoUserAction decide.
Wink Savillee68857d2014-10-17 15:23:05 -07001299 intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001300 newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
Wink Savillee68857d2014-10-17 15:23:05 -07001301 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_SECONDARY;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001302 }
Wink Savillee68857d2014-10-17 15:23:05 -07001303 newIntent.putExtra(SLOT_ID, slotId);
1304 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001305 newIntent.setFlags(intentFlags);
1306 mContext.startActivity(newIntent);
1307 }
1308
Wink Savillee68857d2014-10-17 15:23:05 -07001309 private void launchInputActivity(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001310 Intent newIntent = new Intent(Intent.ACTION_VIEW);
Wink Savillee68857d2014-10-17 15:23:05 -07001311 String targetActivity = STK_INPUT_ACTIVITY_NAME;
1312 String uriString = STK_INPUT_URI + System.currentTimeMillis();
1313 //Set unique URI to create a new instance of activity for different slotId.
1314 Uri uriData = Uri.parse(uriString);
1315
1316 CatLog.d(LOG_TAG, "launchInputActivity, slotId: " + slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001317 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
Wink Savillee68857d2014-10-17 15:23:05 -07001318 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1319 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1320 newIntent.putExtra("INPUT", mStkContext[slotId].mCurrentCmd.geInput());
1321 newIntent.putExtra(SLOT_ID, slotId);
1322 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001323 mContext.startActivity(newIntent);
1324 }
1325
Wink Savillee68857d2014-10-17 15:23:05 -07001326 private void launchTextDialog(int slotId) {
1327 CatLog.d(LOG_TAG, "launchTextDialog, slotId: " + slotId);
1328 Intent newIntent = new Intent();
1329 String targetActivity = STK_DIALOG_ACTIVITY_NAME;
1330 int action = getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
1331 String uriString = STK_DIALOG_URI + System.currentTimeMillis();
1332 //Set unique URI to create a new instance of activity for different slotId.
1333 Uri uriData = Uri.parse(uriString);
1334 if (newIntent != null) {
1335 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1336 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1337 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
1338 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1339 newIntent.setData(uriData);
1340 newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
1341 newIntent.putExtra(SLOT_ID, slotId);
1342 startActivity(newIntent);
Preeti Ahuja414bc412013-06-25 19:31:49 -07001343 // For display texts with immediate response, send the terminal response
1344 // immediately. responseNeeded will be false, if display text command has
1345 // the immediate response tlv.
1346 if (!mStkContext[slotId].mCurrentCmd.geTextMessage().responseNeeded) {
1347 sendResponse(RES_ID_CONFIRM, slotId, true);
1348 }
Wink Savillee68857d2014-10-17 15:23:05 -07001349 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001350 }
1351
Wink Savillee68857d2014-10-17 15:23:05 -07001352 public boolean isStkDialogActivated(Context context) {
1353 String stkDialogActivity = "com.android.stk.StkDialogActivity";
1354 boolean activated = false;
1355 final ActivityManager am = (ActivityManager) context.getSystemService(
1356 Context.ACTIVITY_SERVICE);
1357 String topActivity = am.getRunningTasks(1).get(0).topActivity.getClassName();
1358
1359 CatLog.d(LOG_TAG, "isStkDialogActivated: " + topActivity);
1360 if (topActivity.equals(stkDialogActivity)) {
1361 activated = true;
1362 }
1363 CatLog.d(LOG_TAG, "activated : " + activated);
1364 return activated;
Johan Hellman3aec01c2011-02-10 10:15:28 +01001365 }
1366
Preeti Ahuja95919342013-10-01 18:18:55 -07001367 private void sendSetUpEventResponse(int event, byte[] addedInfo, int slotId) {
Preeti Ahuja414bc412013-06-25 19:31:49 -07001368 CatLog.d(this, "sendSetUpEventResponse: event : " + event + "slotId = " + slotId);
Preeti Ahuja95919342013-10-01 18:18:55 -07001369
1370 if (mStkContext[slotId].mCurrentSetupEventCmd == null){
1371 CatLog.e(this, "mCurrentSetupEventCmd is null");
1372 return;
1373 }
1374
1375 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentSetupEventCmd);
1376
1377 resMsg.setResultCode(ResultCode.OK);
1378 resMsg.setEventDownload(event, addedInfo);
1379
1380 mStkService[slotId].onCmdResponse(resMsg);
1381 }
1382
1383 private void checkForSetupEvent(int event, Bundle args, int slotId) {
1384 boolean eventPresent = false;
1385 byte[] addedInfo = null;
1386 CatLog.d(this, "Event :" + event);
1387
1388 if (mStkContext[slotId].mSetupEventListSettings != null) {
1389 /* Checks if the event is present in the EventList updated by last
1390 * SetupEventList Proactive Command */
1391 for (int i : mStkContext[slotId].mSetupEventListSettings.eventList) {
1392 if (event == i) {
1393 eventPresent = true;
1394 break;
1395 }
1396 }
1397
1398 /* If Event is present send the response to ICC */
1399 if (eventPresent == true) {
1400 CatLog.d(this, " Event " + event + "exists in the EventList");
1401
1402 switch (event) {
Preeti Ahuja560be362014-11-25 19:38:24 -08001403 case IDLE_SCREEN_AVAILABLE_EVENT:
1404 sendSetUpEventResponse(event, addedInfo, slotId);
1405 removeSetUpEvent(event, slotId);
1406 break;
Preeti Ahuja95919342013-10-01 18:18:55 -07001407 case LANGUAGE_SELECTION_EVENT:
1408 String language = mContext
1409 .getResources().getConfiguration().locale.getLanguage();
1410 CatLog.d(this, "language: " + language);
1411 // Each language code is a pair of alpha-numeric characters.
1412 // Each alpha-numeric character shall be coded on one byte
1413 // using the SMS default 7-bit coded alphabet
1414 addedInfo = GsmAlphabet.stringToGsm8BitPacked(language);
1415 sendSetUpEventResponse(event, addedInfo, slotId);
1416 break;
1417 default:
1418 break;
1419 }
1420 } else {
1421 CatLog.e(this, " Event does not exist in the EventList");
1422 }
1423 } else {
1424 CatLog.e(this, "SetupEventList is not received. Ignoring the event: " + event);
1425 }
1426 }
1427
1428 private void removeSetUpEvent(int event, int slotId) {
1429 CatLog.d(this, "Remove Event :" + event);
1430
1431 if (mStkContext[slotId].mSetupEventListSettings != null) {
1432 /*
1433 * Make new Eventlist without the event
1434 */
1435 for (int i = 0; i < mStkContext[slotId].mSetupEventListSettings.eventList.length; i++) {
1436 if (event == mStkContext[slotId].mSetupEventListSettings.eventList[i]) {
1437 mStkContext[slotId].mSetupEventListSettings.eventList[i] = INVALID_SETUP_EVENT;
1438 break;
1439 }
1440 }
1441 }
1442 }
1443
1444 private void launchEventMessage(int slotId) {
1445 launchEventMessage(slotId, mStkContext[slotId].mCurrentCmd.geTextMessage());
1446 }
1447
Wink Savillee68857d2014-10-17 15:23:05 -07001448 private void launchEventMessage(int slotId, TextMessage msg) {
1449 if (msg == null || (msg.text != null && msg.text.length() == 0)) {
1450 CatLog.d(LOG_TAG, "launchEventMessage return");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001451 return;
1452 }
Wink Savillee68857d2014-10-17 15:23:05 -07001453
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001454 Toast toast = new Toast(mContext.getApplicationContext());
1455 LayoutInflater inflate = (LayoutInflater) mContext
1456 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
1457 View v = inflate.inflate(R.layout.stk_event_msg, null);
1458 TextView tv = (TextView) v
1459 .findViewById(com.android.internal.R.id.message);
1460 ImageView iv = (ImageView) v
1461 .findViewById(com.android.internal.R.id.icon);
1462 if (msg.icon != null) {
1463 iv.setImageBitmap(msg.icon);
1464 } else {
1465 iv.setVisibility(View.GONE);
1466 }
1467 if (!msg.iconSelfExplanatory) {
1468 tv.setText(msg.text);
1469 }
1470
1471 toast.setView(v);
1472 toast.setDuration(Toast.LENGTH_LONG);
1473 toast.setGravity(Gravity.BOTTOM, 0, 0);
1474 toast.show();
1475 }
1476
Wink Savillee68857d2014-10-17 15:23:05 -07001477 private void launchConfirmationDialog(TextMessage msg, int slotId) {
1478 msg.title = mStkContext[slotId].lastSelectedItem;
1479 Intent newIntent = new Intent();
1480 String targetActivity = STK_DIALOG_ACTIVITY_NAME;
1481 String uriString = STK_DIALOG_URI + System.currentTimeMillis();
1482 //Set unique URI to create a new instance of activity for different slotId.
1483 Uri uriData = Uri.parse(uriString);
1484
1485 if (newIntent != null) {
1486 newIntent.setClassName(this, targetActivity);
1487 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1488 | Intent.FLAG_ACTIVITY_NO_HISTORY
1489 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
1490 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1491 newIntent.putExtra("TEXT", msg);
1492 newIntent.putExtra(SLOT_ID, slotId);
1493 newIntent.setData(uriData);
1494 startActivity(newIntent);
1495 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001496 }
1497
1498 private void launchBrowser(BrowserSettings settings) {
1499 if (settings == null) {
1500 return;
1501 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001502
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001503 Intent intent = null;
1504 Uri data = null;
David Brown7c03cfe2011-10-20 15:36:12 -07001505
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001506 if (settings.url != null) {
Wink Savillee68857d2014-10-17 15:23:05 -07001507 CatLog.d(LOG_TAG, "settings.url = " + settings.url);
dujin.cha2a0eb2a2011-11-11 15:03:57 +09001508 if ((settings.url.startsWith("http://") || (settings.url.startsWith("https://")))) {
dujin.cha486c1d02011-11-02 22:14:25 +09001509 data = Uri.parse(settings.url);
1510 } else {
1511 String modifiedUrl = "http://" + settings.url;
Wink Savillee68857d2014-10-17 15:23:05 -07001512 CatLog.d(LOG_TAG, "modifiedUrl = " + modifiedUrl);
dujin.cha486c1d02011-11-02 22:14:25 +09001513 data = Uri.parse(modifiedUrl);
1514 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001515 }
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001516 if (data != null) {
1517 intent = new Intent(Intent.ACTION_VIEW);
1518 intent.setData(data);
1519 } else {
1520 // if the command did not contain a URL,
1521 // launch the browser to the default homepage.
Wink Savillee68857d2014-10-17 15:23:05 -07001522 CatLog.d(LOG_TAG, "launch browser with default URL ");
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001523 intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN,
1524 Intent.CATEGORY_APP_BROWSER);
1525 }
David Brown7c03cfe2011-10-20 15:36:12 -07001526
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001527 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1528 switch (settings.mode) {
1529 case USE_EXISTING_BROWSER:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001530 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1531 break;
1532 case LAUNCH_NEW_BROWSER:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001533 intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
1534 break;
1535 case LAUNCH_IF_NOT_ALREADY_LAUNCHED:
1536 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1537 break;
1538 }
1539 // start browser activity
1540 startActivity(intent);
1541 // a small delay, let the browser start, before processing the next command.
Wink Saville79085fc2009-06-09 10:27:23 -07001542 // this is good for scenarios where a related DISPLAY TEXT command is
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001543 // followed immediately.
1544 try {
1545 Thread.sleep(10000);
1546 } catch (InterruptedException e) {}
1547 }
1548
Wink Savillee68857d2014-10-17 15:23:05 -07001549 private void launchIdleText(int slotId) {
Preeti Ahuja560be362014-11-25 19:38:24 -08001550 TextMessage msg = mStkContext[slotId].mIdleModeTextCmd.geTextMessage();
dujin.cha2a0eb2a2011-11-11 15:03:57 +09001551
Preeti Ahuja95919342013-10-01 18:18:55 -07001552 if (msg == null || msg.text ==null) {
1553 CatLog.d(LOG_TAG, msg == null ? "mCurrent.getTextMessage is NULL"
1554 : "mCurrent.getTextMessage.text is NULL");
Wink Savillee68857d2014-10-17 15:23:05 -07001555 mNotificationManager.cancel(getNotificationId(slotId));
Wink Saville046db4b2011-11-01 20:42:54 -07001556 return;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001557 } else {
Preeti Ahuja95919342013-10-01 18:18:55 -07001558 CatLog.d(LOG_TAG, "launchIdleText - text[" + msg.text
1559 + "] iconSelfExplanatory[" + msg.iconSelfExplanatory
1560 + "] icon[" + msg.icon + "], sim id: " + slotId);
Wink Savillee68857d2014-10-17 15:23:05 -07001561 CatLog.d(LOG_TAG, "Add IdleMode text");
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001562 PendingIntent pendingIntent = PendingIntent.getService(mContext, 0,
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001563 new Intent(mContext, StkAppService.class), 0);
1564
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001565 final Notification.Builder notificationBuilder = new Notification.Builder(
1566 StkAppService.this);
Wink Savillee68857d2014-10-17 15:23:05 -07001567 if (mStkContext[slotId].mMainCmd != null &&
1568 mStkContext[slotId].mMainCmd.getMenu() != null) {
1569 notificationBuilder.setContentTitle(mStkContext[slotId].mMainCmd.getMenu().title);
Christopher Posselwhite2ad2ab72013-05-27 07:51:06 +02001570 } else {
1571 notificationBuilder.setContentTitle("");
1572 }
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001573 notificationBuilder
1574 .setSmallIcon(com.android.internal.R.drawable.stat_notify_sim_toolkit);
1575 notificationBuilder.setContentIntent(pendingIntent);
1576 notificationBuilder.setOngoing(true);
1577 // Set text and icon for the status bar and notification body.
1578 if (!msg.iconSelfExplanatory) {
1579 notificationBuilder.setContentText(msg.text);
Christopher Posselwhite2ad2ab72013-05-27 07:51:06 +02001580 notificationBuilder.setTicker(msg.text);
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001581 }
1582 if (msg.icon != null) {
1583 notificationBuilder.setLargeIcon(msg.icon);
1584 } else {
1585 Bitmap bitmapIcon = BitmapFactory.decodeResource(StkAppService.this
1586 .getResources().getSystem(),
1587 com.android.internal.R.drawable.stat_notify_sim_toolkit);
1588 notificationBuilder.setLargeIcon(bitmapIcon);
1589 }
Selim Cinek62eb3fe2014-08-27 17:52:23 +02001590 notificationBuilder.setColor(mContext.getResources().getColor(
1591 com.android.internal.R.color.system_notification_accent_color));
Wink Savillee68857d2014-10-17 15:23:05 -07001592 mNotificationManager.notify(getNotificationId(slotId), notificationBuilder.build());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001593 }
1594 }
1595
Wink Savillee68857d2014-10-17 15:23:05 -07001596 private void launchToneDialog(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001597 Intent newIntent = new Intent(this, ToneDialog.class);
Wink Savillee68857d2014-10-17 15:23:05 -07001598 String uriString = STK_TONE_URI + slotId;
1599 Uri uriData = Uri.parse(uriString);
1600 //Set unique URI to create a new instance of activity for different slotId.
1601 CatLog.d(LOG_TAG, "launchToneDialog, slotId: " + slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001602 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1603 | Intent.FLAG_ACTIVITY_NO_HISTORY
1604 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
Wink Savillee68857d2014-10-17 15:23:05 -07001605 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1606 newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
1607 newIntent.putExtra("TONE", mStkContext[slotId].mCurrentCmd.getToneSettings());
1608 newIntent.putExtra(SLOT_ID, slotId);
1609 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001610 startActivity(newIntent);
1611 }
1612
Wink Savillee68857d2014-10-17 15:23:05 -07001613 private void launchOpenChannelDialog(int slotId) {
1614 TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001615 if (msg == null) {
Wink Savillee68857d2014-10-17 15:23:05 -07001616 CatLog.d(LOG_TAG, "msg is null, return here");
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001617 return;
1618 }
1619
1620 msg.title = getResources().getString(R.string.stk_dialog_title);
1621 if (msg.text == null) {
1622 msg.text = getResources().getString(R.string.default_open_channel_msg);
1623 }
1624
1625 final AlertDialog dialog = new AlertDialog.Builder(mContext)
1626 .setIconAttribute(android.R.attr.alertDialogIcon)
1627 .setTitle(msg.title)
1628 .setMessage(msg.text)
1629 .setCancelable(false)
1630 .setPositiveButton(getResources().getString(R.string.stk_dialog_accept),
1631 new DialogInterface.OnClickListener() {
1632 public void onClick(DialogInterface dialog, int which) {
1633 Bundle args = new Bundle();
1634 args.putInt(RES_ID, RES_ID_CHOICE);
1635 args.putInt(CHOICE, YES);
1636 Message message = mServiceHandler.obtainMessage();
1637 message.arg1 = OP_RESPONSE;
1638 message.obj = args;
1639 mServiceHandler.sendMessage(message);
1640 }
1641 })
1642 .setNegativeButton(getResources().getString(R.string.stk_dialog_reject),
1643 new DialogInterface.OnClickListener() {
1644 public void onClick(DialogInterface dialog, int which) {
1645 Bundle args = new Bundle();
1646 args.putInt(RES_ID, RES_ID_CHOICE);
1647 args.putInt(CHOICE, NO);
1648 Message message = mServiceHandler.obtainMessage();
1649 message.arg1 = OP_RESPONSE;
1650 message.obj = args;
1651 mServiceHandler.sendMessage(message);
1652 }
1653 })
1654 .create();
1655
1656 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1657 if (!mContext.getResources().getBoolean(
1658 com.android.internal.R.bool.config_sf_slowBlur)) {
1659 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
1660 }
1661
1662 dialog.show();
1663 }
1664
Wink Savillee68857d2014-10-17 15:23:05 -07001665 private void launchTransientEventMessage(int slotId) {
1666 TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001667 if (msg == null) {
Wink Savillee68857d2014-10-17 15:23:05 -07001668 CatLog.d(LOG_TAG, "msg is null, return here");
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001669 return;
1670 }
1671
1672 msg.title = getResources().getString(R.string.stk_dialog_title);
1673
1674 final AlertDialog dialog = new AlertDialog.Builder(mContext)
1675 .setIconAttribute(android.R.attr.alertDialogIcon)
1676 .setTitle(msg.title)
1677 .setMessage(msg.text)
1678 .setCancelable(false)
1679 .setPositiveButton(getResources().getString(android.R.string.ok),
1680 new DialogInterface.OnClickListener() {
1681 public void onClick(DialogInterface dialog, int which) {
1682 }
1683 })
1684 .create();
1685
1686 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1687 if (!mContext.getResources().getBoolean(
1688 com.android.internal.R.bool.config_sf_slowBlur)) {
1689 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
1690 }
1691
1692 dialog.show();
1693 }
1694
Wink Savillee68857d2014-10-17 15:23:05 -07001695 private int getNotificationId(int slotId) {
1696 int notifyId = STK_NOTIFICATION_ID;
1697 if (slotId >= 0 && slotId < mSimCount) {
1698 notifyId += slotId;
1699 } else {
1700 CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
1701 }
1702 CatLog.d(LOG_TAG, "getNotificationId, slotId: " + slotId + ", notifyId: " + notifyId);
1703 return notifyId;
1704 }
1705
1706 private String getItemName(int itemId, int slotId) {
1707 Menu menu = mStkContext[slotId].mCurrentCmd.getMenu();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001708 if (menu == null) {
1709 return null;
1710 }
1711 for (Item item : menu.items) {
1712 if (item.id == itemId) {
1713 return item.text;
1714 }
1715 }
1716 return null;
1717 }
1718
Wink Savillee68857d2014-10-17 15:23:05 -07001719 private boolean removeMenu(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001720 try {
Wink Savillee68857d2014-10-17 15:23:05 -07001721 if (mStkContext[slotId].mCurrentMenu.items.size() == 1 &&
1722 mStkContext[slotId].mCurrentMenu.items.get(0) == null) {
1723 mStkContext[slotId].mSetupMenuState = STATE_NOT_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001724 return true;
1725 }
1726 } catch (NullPointerException e) {
Wink Savillee68857d2014-10-17 15:23:05 -07001727 CatLog.d(LOG_TAG, "Unable to get Menu's items size");
1728 mStkContext[slotId].mSetupMenuState = STATE_NOT_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001729 return true;
1730 }
Wink Savillee68857d2014-10-17 15:23:05 -07001731 mStkContext[slotId].mSetupMenuState = STATE_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001732 return false;
1733 }
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +05301734
Wink Savillee68857d2014-10-17 15:23:05 -07001735 StkContext getStkContext(int slotId) {
1736 if (slotId >= 0 && slotId < mSimCount) {
1737 return mStkContext[slotId];
1738 } else {
1739 CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
1740 return null;
1741 }
1742 }
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +05301743
1744 private void handleAlphaNotify(Bundle args) {
1745 String alphaString = args.getString(AppInterface.ALPHA_STRING);
1746
1747 CatLog.d(this, "Alpha string received from card: " + alphaString);
1748 Toast toast = Toast.makeText(sInstance, alphaString, Toast.LENGTH_LONG);
1749 toast.setGravity(Gravity.TOP, 0, 0);
1750 toast.show();
1751 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001752}