blob: 7f32624ac6a5dcd2910554e0d1ffe69158934738 [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;
Preeti Ahujaa7cdca22013-10-01 18:20:56 -070030import android.content.ComponentName;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080031import android.content.Context;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -050032import android.content.DialogInterface;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080033import android.content.Intent;
Preeti Ahuja95919342013-10-01 18:18:55 -070034import android.content.res.Configuration;
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +010035import android.graphics.Bitmap;
36import android.graphics.BitmapFactory;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080037import android.net.Uri;
38import android.os.Bundle;
39import android.os.Handler;
40import android.os.IBinder;
41import android.os.Looper;
42import android.os.Message;
Preeti Ahuja560be362014-11-25 19:38:24 -080043import android.os.PowerManager;
Preeti Ahujaa7cdca22013-10-01 18:20:56 -070044import android.os.SystemProperties;
Preeti Ahuja95919342013-10-01 18:18:55 -070045import android.provider.Settings;
Wink Saville56469d52009-04-02 01:37:03 -070046import android.telephony.TelephonyManager;
Preeti Ahujaa7cdca22013-10-01 18:20:56 -070047import android.text.TextUtils;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080048import android.view.Gravity;
49import android.view.LayoutInflater;
50import android.view.View;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -050051import android.view.Window;
52import android.view.WindowManager;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080053import android.widget.ImageView;
54import android.widget.RemoteViews;
55import android.widget.TextView;
56import android.widget.Toast;
Wink Savillee68857d2014-10-17 15:23:05 -070057import android.content.BroadcastReceiver;
58import android.content.IntentFilter;
59import android.content.pm.ApplicationInfo;
60import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080061
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070062import com.android.internal.telephony.cat.AppInterface;
Preeti Ahuja95919342013-10-01 18:18:55 -070063import com.android.internal.telephony.cat.LaunchBrowserMode;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070064import com.android.internal.telephony.cat.Menu;
65import com.android.internal.telephony.cat.Item;
Pierre Fröjd97503262010-11-08 13:59:36 +010066import com.android.internal.telephony.cat.Input;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070067import com.android.internal.telephony.cat.ResultCode;
68import com.android.internal.telephony.cat.CatCmdMessage;
69import com.android.internal.telephony.cat.CatCmdMessage.BrowserSettings;
Preeti Ahuja95919342013-10-01 18:18:55 -070070import com.android.internal.telephony.cat.CatCmdMessage.SetupEventListSettings;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070071import com.android.internal.telephony.cat.CatLog;
72import com.android.internal.telephony.cat.CatResponseMessage;
73import com.android.internal.telephony.cat.TextMessage;
Wink Saville94e982b2014-07-11 07:38:14 -070074import com.android.internal.telephony.uicc.IccRefreshResponse;
75import com.android.internal.telephony.uicc.IccCardStatus.CardState;
Wink Savillee68857d2014-10-17 15:23:05 -070076import com.android.internal.telephony.PhoneConstants;
77import com.android.internal.telephony.TelephonyIntents;
78import com.android.internal.telephony.IccCardConstants;
79import com.android.internal.telephony.uicc.UiccController;
Preeti Ahuja95919342013-10-01 18:18:55 -070080import com.android.internal.telephony.GsmAlphabet;
Legler Wuaeefef52014-10-27 00:57:18 +080081import com.android.internal.telephony.cat.CatService;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080082
Preeti Ahujaa7cdca22013-10-01 18:20:56 -070083import java.util.Iterator;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080084import java.util.LinkedList;
Wink Savillee68857d2014-10-17 15:23:05 -070085import java.lang.System;
86import java.util.List;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080087
Preeti Ahuja95919342013-10-01 18:18:55 -070088import static com.android.internal.telephony.cat.CatCmdMessage.
Preeti Ahuja560be362014-11-25 19:38:24 -080089 SetupEventListConstants.IDLE_SCREEN_AVAILABLE_EVENT;
90import static com.android.internal.telephony.cat.CatCmdMessage.
Preeti Ahuja95919342013-10-01 18:18:55 -070091 SetupEventListConstants.LANGUAGE_SELECTION_EVENT;
92
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080093/**
94 * SIM toolkit application level service. Interacts with Telephopny messages,
95 * application's launch and user input from STK UI elements.
Wink Saville79085fc2009-06-09 10:27:23 -070096 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080097 */
98public class StkAppService extends Service implements Runnable {
99
100 // members
Wink Savillee68857d2014-10-17 15:23:05 -0700101 protected class StkContext {
102 protected CatCmdMessage mMainCmd = null;
103 protected CatCmdMessage mCurrentCmd = null;
104 protected CatCmdMessage mCurrentMenuCmd = null;
105 protected Menu mCurrentMenu = null;
106 protected String lastSelectedItem = null;
107 protected boolean mMenuIsVisible = false;
108 protected boolean mIsInputPending = false;
109 protected boolean mIsMenuPending = false;
110 protected boolean mIsDialogPending = false;
111 protected boolean responseNeeded = true;
112 protected boolean launchBrowser = false;
113 protected BrowserSettings mBrowserSettings = null;
114 protected LinkedList<DelayedCmd> mCmdsQ = null;
115 protected boolean mCmdInProgress = false;
116 protected int mStkServiceState = STATE_UNKNOWN;
117 protected int mSetupMenuState = STATE_UNKNOWN;
118 protected int mMenuState = StkMenuActivity.STATE_INIT;
119 protected int mOpCode = -1;
120 private Activity mActivityInstance = null;
121 private Activity mDialogInstance = null;
122 private Activity mMainActivityInstance = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700123 private int mSlotId = 0;
Preeti Ahuja95919342013-10-01 18:18:55 -0700124 private SetupEventListSettings mSetupEventListSettings = null;
125 private boolean mClearSelectItem = false;
126 private boolean mDisplayTextDlgIsVisibile = false;
127 private CatCmdMessage mCurrentSetupEventCmd = null;
Preeti Ahuja560be362014-11-25 19:38:24 -0800128 private CatCmdMessage mIdleModeTextCmd = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700129 final synchronized void setPendingActivityInstance(Activity act) {
130 CatLog.d(this, "setPendingActivityInstance act : " + mSlotId + ", " + act);
131 callSetActivityInstMsg(OP_SET_ACT_INST, mSlotId, act);
132 }
133 final synchronized Activity getPendingActivityInstance() {
134 CatLog.d(this, "getPendingActivityInstance act : " + mSlotId + ", " +
135 mActivityInstance);
136 return mActivityInstance;
137 }
138 final synchronized void setPendingDialogInstance(Activity act) {
139 CatLog.d(this, "setPendingDialogInstance act : " + mSlotId + ", " + act);
140 callSetActivityInstMsg(OP_SET_DAL_INST, mSlotId, act);
141 }
142 final synchronized Activity getPendingDialogInstance() {
143 CatLog.d(this, "getPendingDialogInstance act : " + mSlotId + ", " +
144 mDialogInstance);
145 return mDialogInstance;
146 }
147 final synchronized void setMainActivityInstance(Activity act) {
148 CatLog.d(this, "setMainActivityInstance act : " + mSlotId + ", " + act);
149 callSetActivityInstMsg(OP_SET_MAINACT_INST, mSlotId, act);
150 }
151 final synchronized Activity getMainActivityInstance() {
152 CatLog.d(this, "getMainActivityInstance act : " + mSlotId + ", " +
153 mMainActivityInstance);
154 return mMainActivityInstance;
155 }
156 }
157
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800158 private volatile Looper mServiceLooper;
159 private volatile ServiceHandler mServiceHandler;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800160 private Context mContext = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800161 private NotificationManager mNotificationManager = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800162 static StkAppService sInstance = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700163 private AppInterface[] mStkService = null;
164 private StkContext[] mStkContext = null;
165 private int mSimCount = 0;
Preeti Ahuja560be362014-11-25 19:38:24 -0800166 private PowerManager mPowerManager = null;
167 private StkCmdReceiver mStkCmdReceiver = null;
Preeti Ahuja95919342013-10-01 18:18:55 -0700168
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800169 // Used for setting FLAG_ACTIVITY_NO_USER_ACTION when
170 // creating an intent.
171 private enum InitiatedByUserAction {
172 yes, // The action was started via a user initiated action
173 unknown, // Not known for sure if user initated the action
174 }
175
176 // constants
177 static final String OPCODE = "op";
178 static final String CMD_MSG = "cmd message";
179 static final String RES_ID = "response id";
180 static final String MENU_SELECTION = "menu selection";
181 static final String INPUT = "input";
182 static final String HELP = "help";
183 static final String CONFIRMATION = "confirm";
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500184 static final String CHOICE = "choice";
Wink Savillee68857d2014-10-17 15:23:05 -0700185 static final String SLOT_ID = "SLOT_ID";
186 static final String STK_CMD = "STK CMD";
187 static final String STK_DIALOG_URI = "stk://com.android.stk/dialog/";
188 static final String STK_MENU_URI = "stk://com.android.stk/menu/";
189 static final String STK_INPUT_URI = "stk://com.android.stk/input/";
190 static final String STK_TONE_URI = "stk://com.android.stk/tone/";
Preeti Ahuja95919342013-10-01 18:18:55 -0700191
192 // These below constants are used for SETUP_EVENT_LIST
193 static final String SETUP_EVENT_TYPE = "event";
194 static final String SETUP_EVENT_CAUSE = "cause";
195
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800196 // operations ids for different service functionality.
197 static final int OP_CMD = 1;
198 static final int OP_RESPONSE = 2;
199 static final int OP_LAUNCH_APP = 3;
200 static final int OP_END_SESSION = 4;
201 static final int OP_BOOT_COMPLETED = 5;
202 private static final int OP_DELAYED_MSG = 6;
Wink Saville94e982b2014-07-11 07:38:14 -0700203 static final int OP_CARD_STATUS_CHANGED = 7;
Wink Savillee68857d2014-10-17 15:23:05 -0700204 static final int OP_SET_ACT_INST = 8;
205 static final int OP_SET_DAL_INST = 9;
206 static final int OP_SET_MAINACT_INST = 10;
Preeti Ahujab3d0e612014-11-20 13:29:25 -0800207 static final int OP_LOCALE_CHANGED = 11;
208 static final int OP_ALPHA_NOTIFY = 12;
Preeti Ahuja560be362014-11-25 19:38:24 -0800209 static final int OP_IDLE_SCREEN = 13;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800210
Preeti Ahuja95919342013-10-01 18:18:55 -0700211 //Invalid SetupEvent
212 static final int INVALID_SETUP_EVENT = 0xFF;
213
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800214 // Response ids
215 static final int RES_ID_MENU_SELECTION = 11;
216 static final int RES_ID_INPUT = 12;
217 static final int RES_ID_CONFIRM = 13;
218 static final int RES_ID_DONE = 14;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500219 static final int RES_ID_CHOICE = 15;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800220
221 static final int RES_ID_TIMEOUT = 20;
222 static final int RES_ID_BACKWARD = 21;
223 static final int RES_ID_END_SESSION = 22;
224 static final int RES_ID_EXIT = 23;
225
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500226 static final int YES = 1;
227 static final int NO = 0;
228
Wink Savillee68857d2014-10-17 15:23:05 -0700229 static final int STATE_UNKNOWN = -1;
230 static final int STATE_NOT_EXIST = 0;
231 static final int STATE_EXIST = 1;
Wink Saville79085fc2009-06-09 10:27:23 -0700232
Wink Savillee68857d2014-10-17 15:23:05 -0700233 private static final String PACKAGE_NAME = "com.android.stk";
234 private static final String STK_MENU_ACTIVITY_NAME = PACKAGE_NAME + ".StkMenuActivity";
235 private static final String STK_INPUT_ACTIVITY_NAME = PACKAGE_NAME + ".StkInputActivity";
236 private static final String STK_DIALOG_ACTIVITY_NAME = PACKAGE_NAME + ".StkDialogActivity";
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800237 // Notification id used to display Idle Mode text in NotificationManager.
238 private static final int STK_NOTIFICATION_ID = 333;
Wink Savillee68857d2014-10-17 15:23:05 -0700239 private static final String LOG_TAG = new Object(){}.getClass().getEnclosingClass().getName();
Wink Saville79085fc2009-06-09 10:27:23 -0700240
241 // Inner class used for queuing telephony messages (proactive commands,
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800242 // session end) while the service is busy processing a previous message.
243 private class DelayedCmd {
244 // members
245 int id;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700246 CatCmdMessage msg;
Wink Savillee68857d2014-10-17 15:23:05 -0700247 int slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800248
Wink Savillee68857d2014-10-17 15:23:05 -0700249 DelayedCmd(int id, CatCmdMessage msg, int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800250 this.id = id;
251 this.msg = msg;
Wink Savillee68857d2014-10-17 15:23:05 -0700252 this.slotId = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800253 }
254 }
255
Preeti Ahujaa7cdca22013-10-01 18:20:56 -0700256 // system property to set the STK specific default url for launch browser proactive cmds
257 private static final String STK_BROWSER_DEFAULT_URL_SYSPROP = "persist.radio.stk.default_url";
258
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800259 @Override
260 public void onCreate() {
Wink Savillee68857d2014-10-17 15:23:05 -0700261 CatLog.d(LOG_TAG, "onCreate()+");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800262 // Initialize members
Wink Savillee68857d2014-10-17 15:23:05 -0700263 int i = 0;
264 mContext = getBaseContext();
265 mSimCount = TelephonyManager.from(mContext).getSimCount();
266 CatLog.d(LOG_TAG, "simCount: " + mSimCount);
267 mStkService = new AppInterface[mSimCount];
268 mStkContext = new StkContext[mSimCount];
Preeti Ahuja560be362014-11-25 19:38:24 -0800269 mPowerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
270 mStkCmdReceiver = new StkCmdReceiver();
271 registerReceiver(mStkCmdReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
Wink Savillee68857d2014-10-17 15:23:05 -0700272 for (i = 0; i < mSimCount; i++) {
273 CatLog.d(LOG_TAG, "slotId: " + i);
Legler Wuaeefef52014-10-27 00:57:18 +0800274 mStkService[i] = CatService.getInstance(i);
Wink Savillee68857d2014-10-17 15:23:05 -0700275 mStkContext[i] = new StkContext();
276 mStkContext[i].mSlotId = i;
277 mStkContext[i].mCmdsQ = new LinkedList<DelayedCmd>();
278 }
279
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800280 Thread serviceThread = new Thread(null, this, "Stk App Service");
281 serviceThread.start();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800282 mNotificationManager = (NotificationManager) mContext
283 .getSystemService(Context.NOTIFICATION_SERVICE);
284 sInstance = this;
285 }
286
287 @Override
288 public void onStart(Intent intent, int startId) {
Wink Savillee68857d2014-10-17 15:23:05 -0700289 if (intent == null) {
290 CatLog.d(LOG_TAG, "StkAppService onStart intent is null so return");
Banavathu, Srinivas Naik87cda962012-07-17 15:32:44 +0530291 return;
292 }
293
Wink Savillee68857d2014-10-17 15:23:05 -0700294 Bundle args = intent.getExtras();
295 if (args == null) {
296 CatLog.d(LOG_TAG, "StkAppService onStart args is null so return");
297 return;
298 }
299
300 int op = args.getInt(OPCODE);
301 int slotId = 0;
302 int i = 0;
303 if (op != OP_BOOT_COMPLETED) {
304 slotId = args.getInt(SLOT_ID);
305 }
Cuihtlauac ALVARADObde7f032015-05-29 16:25:12 +0200306 CatLog.d(LOG_TAG, "onStart sim id: " + slotId + ", op: " + op + ", *****");
Wink Savillee68857d2014-10-17 15:23:05 -0700307 if ((slotId >= 0 && slotId < mSimCount) && mStkService[slotId] == null) {
Legler Wuaeefef52014-10-27 00:57:18 +0800308 mStkService[slotId] = CatService.getInstance(slotId);
Wink Savillee68857d2014-10-17 15:23:05 -0700309 if (mStkService[slotId] == null) {
310 CatLog.d(LOG_TAG, "mStkService is: " + mStkContext[slotId].mStkServiceState);
311 mStkContext[slotId].mStkServiceState = STATE_NOT_EXIST;
312 //Check other StkService state.
313 //If all StkServices are not available, stop itself and uninstall apk.
314 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
315 if (i != slotId
Tsukasa Goto029332b2016-10-05 17:12:06 +0900316 && (mStkService[i] != null)
Wink Savillee68857d2014-10-17 15:23:05 -0700317 && (mStkContext[i].mStkServiceState == STATE_UNKNOWN
318 || mStkContext[i].mStkServiceState == STATE_EXIST)) {
319 break;
320 }
321 }
322 } else {
323 mStkContext[slotId].mStkServiceState = STATE_EXIST;
324 }
325 if (i == mSimCount) {
326 stopSelf();
327 StkAppInstaller.unInstall(mContext);
328 return;
329 }
330 }
331
Banavathu, Srinivas Naik87cda962012-07-17 15:32:44 +0530332 waitForLooper();
John Wang62acae42009-10-08 11:20:23 -0700333
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800334 Message msg = mServiceHandler.obtainMessage();
Wink Savillee68857d2014-10-17 15:23:05 -0700335 msg.arg1 = op;
336 msg.arg2 = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800337 switch(msg.arg1) {
338 case OP_CMD:
339 msg.obj = args.getParcelable(CMD_MSG);
340 break;
341 case OP_RESPONSE:
Wink Saville94e982b2014-07-11 07:38:14 -0700342 case OP_CARD_STATUS_CHANGED:
Preeti Ahuja95919342013-10-01 18:18:55 -0700343 case OP_LOCALE_CHANGED:
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +0530344 case OP_ALPHA_NOTIFY:
Preeti Ahuja560be362014-11-25 19:38:24 -0800345 case OP_IDLE_SCREEN:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800346 msg.obj = args;
347 /* falls through */
348 case OP_LAUNCH_APP:
349 case OP_END_SESSION:
350 case OP_BOOT_COMPLETED:
351 break;
352 default:
353 return;
354 }
355 mServiceHandler.sendMessage(msg);
356 }
357
358 @Override
359 public void onDestroy() {
Wink Savillee68857d2014-10-17 15:23:05 -0700360 CatLog.d(LOG_TAG, "onDestroy()");
Preeti Ahuja560be362014-11-25 19:38:24 -0800361 if (mStkCmdReceiver != null) {
362 unregisterReceiver(mStkCmdReceiver);
363 mStkCmdReceiver = null;
364 }
365 mPowerManager = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800366 waitForLooper();
367 mServiceLooper.quit();
368 }
369
370 @Override
371 public IBinder onBind(Intent intent) {
372 return null;
373 }
374
375 public void run() {
376 Looper.prepare();
377
378 mServiceLooper = Looper.myLooper();
379 mServiceHandler = new ServiceHandler();
380
381 Looper.loop();
382 }
383
384 /*
385 * Package api used by StkMenuActivity to indicate if its on the foreground.
386 */
Wink Savillee68857d2014-10-17 15:23:05 -0700387 void indicateMenuVisibility(boolean visibility, int slotId) {
388 if (slotId >= 0 && slotId < mSimCount) {
389 mStkContext[slotId].mMenuIsVisible = visibility;
390 }
391 }
392
Preeti Ahuja95919342013-10-01 18:18:55 -0700393 /*
394 * Package api used by StkDialogActivity to indicate if its on the foreground.
395 */
396 void setDisplayTextDlgVisibility(boolean visibility, int slotId) {
397 if (slotId >= 0 && slotId < mSimCount) {
398 mStkContext[slotId].mDisplayTextDlgIsVisibile = visibility;
399 }
400 }
401
Wink Savillee68857d2014-10-17 15:23:05 -0700402 boolean isInputPending(int slotId) {
403 if (slotId >= 0 && slotId < mSimCount) {
404 CatLog.d(LOG_TAG, "isInputFinishBySrv: " + mStkContext[slotId].mIsInputPending);
405 return mStkContext[slotId].mIsInputPending;
406 }
407 return false;
408 }
409
410 boolean isMenuPending(int slotId) {
411 if (slotId >= 0 && slotId < mSimCount) {
412 CatLog.d(LOG_TAG, "isMenuPending: " + mStkContext[slotId].mIsMenuPending);
413 return mStkContext[slotId].mIsMenuPending;
414 }
415 return false;
416 }
417
418 boolean isDialogPending(int slotId) {
419 if (slotId >= 0 && slotId < mSimCount) {
420 CatLog.d(LOG_TAG, "isDialogPending: " + mStkContext[slotId].mIsDialogPending);
421 return mStkContext[slotId].mIsDialogPending;
422 }
423 return false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800424 }
425
426 /*
427 * Package api used by StkMenuActivity to get its Menu parameter.
428 */
Wink Savillee68857d2014-10-17 15:23:05 -0700429 Menu getMenu(int slotId) {
430 CatLog.d(LOG_TAG, "StkAppService, getMenu, sim id: " + slotId);
431 if (slotId >=0 && slotId < mSimCount) {
432 return mStkContext[slotId].mCurrentMenu;
433 } else {
434 return null;
435 }
436 }
437
438 /*
439 * Package api used by StkMenuActivity to get its Main Menu parameter.
440 */
441 Menu getMainMenu(int slotId) {
442 CatLog.d(LOG_TAG, "StkAppService, getMainMenu, sim id: " + slotId);
w30234a08cffe2015-02-04 15:13:25 -0800443 if (slotId >=0 && slotId < mSimCount && (mStkContext[slotId].mMainCmd != null)) {
Wink Savillee68857d2014-10-17 15:23:05 -0700444 return mStkContext[slotId].mMainCmd.getMenu();
445 } else {
446 return null;
447 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800448 }
449
450 /*
451 * Package api used by UI Activities and Dialogs to communicate directly
452 * with the service to deliver state information and parameters.
453 */
454 static StkAppService getInstance() {
455 return sInstance;
456 }
457
458 private void waitForLooper() {
459 while (mServiceHandler == null) {
460 synchronized (this) {
461 try {
462 wait(100);
463 } catch (InterruptedException e) {
464 }
465 }
466 }
467 }
468
469 private final class ServiceHandler extends Handler {
470 @Override
471 public void handleMessage(Message msg) {
Wink Savillee68857d2014-10-17 15:23:05 -0700472 if(null == msg) {
473 CatLog.d(LOG_TAG, "ServiceHandler handleMessage msg is null");
474 return;
475 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800476 int opcode = msg.arg1;
Wink Savillee68857d2014-10-17 15:23:05 -0700477 int slotId = msg.arg2;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800478
Wink Savillee68857d2014-10-17 15:23:05 -0700479 CatLog.d(LOG_TAG, "handleMessage opcode[" + opcode + "], sim id[" + slotId + "]");
480 if (opcode == OP_CMD && msg.obj != null &&
481 ((CatCmdMessage)msg.obj).getCmdType()!= null) {
482 CatLog.d(LOG_TAG, "cmdName[" + ((CatCmdMessage)msg.obj).getCmdType().name() + "]");
483 }
484 mStkContext[slotId].mOpCode = opcode;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800485 switch (opcode) {
486 case OP_LAUNCH_APP:
Wink Savillee68857d2014-10-17 15:23:05 -0700487 if (mStkContext[slotId].mMainCmd == null) {
488 CatLog.d(LOG_TAG, "mMainCmd is null");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800489 // nothing todo when no SET UP MENU command didn't arrive.
490 return;
491 }
Wink Savillee68857d2014-10-17 15:23:05 -0700492 CatLog.d(LOG_TAG, "handleMessage OP_LAUNCH_APP - mCmdInProgress[" +
493 mStkContext[slotId].mCmdInProgress + "]");
494
495 //If there is a pending activity for the slot id,
496 //just finish it and create a new one to handle the pending command.
497 cleanUpInstanceStackBySlot(slotId);
498
Wink Savillee68857d2014-10-17 15:23:05 -0700499 CatLog.d(LOG_TAG, "Current cmd type: " +
500 mStkContext[slotId].mCurrentCmd.getCmdType());
501 //Restore the last command from stack by slot id.
502 restoreInstanceFromStackBySlot(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800503 break;
504 case OP_CMD:
Wink Savillee68857d2014-10-17 15:23:05 -0700505 CatLog.d(LOG_TAG, "[OP_CMD]");
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700506 CatCmdMessage cmdMsg = (CatCmdMessage) msg.obj;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800507 // There are two types of commands:
508 // 1. Interactive - user's response is required.
509 // 2. Informative - display a message, no interaction with the user.
510 //
Wink Saville79085fc2009-06-09 10:27:23 -0700511 // Informative commands can be handled immediately without any delay.
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800512 // Interactive commands can't override each other. So if a command
513 // is already in progress, we need to queue the next command until
514 // the user has responded or a timeout expired.
515 if (!isCmdInteractive(cmdMsg)) {
Wink Savillee68857d2014-10-17 15:23:05 -0700516 handleCmd(cmdMsg, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800517 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700518 if (!mStkContext[slotId].mCmdInProgress) {
519 mStkContext[slotId].mCmdInProgress = true;
520 handleCmd((CatCmdMessage) msg.obj, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800521 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700522 CatLog.d(LOG_TAG, "[Interactive][in progress]");
523 mStkContext[slotId].mCmdsQ.addLast(new DelayedCmd(OP_CMD,
524 (CatCmdMessage) msg.obj, slotId));
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800525 }
526 }
527 break;
528 case OP_RESPONSE:
Preeti Ahuja414bc412013-06-25 19:31:49 -0700529 handleCmdResponse((Bundle) msg.obj, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800530 // call delayed commands if needed.
Wink Savillee68857d2014-10-17 15:23:05 -0700531 if (mStkContext[slotId].mCmdsQ.size() != 0) {
532 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800533 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700534 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800535 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800536 break;
537 case OP_END_SESSION:
Wink Savillee68857d2014-10-17 15:23:05 -0700538 if (!mStkContext[slotId].mCmdInProgress) {
539 mStkContext[slotId].mCmdInProgress = true;
540 handleSessionEnd(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800541 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700542 mStkContext[slotId].mCmdsQ.addLast(
543 new DelayedCmd(OP_END_SESSION, null, slotId));
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800544 }
545 break;
546 case OP_BOOT_COMPLETED:
Wink Savillee68857d2014-10-17 15:23:05 -0700547 CatLog.d(LOG_TAG, " OP_BOOT_COMPLETED");
548 int i = 0;
549 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
550 if (mStkContext[i].mMainCmd != null) {
551 break;
552 }
553 }
554 if (i == mSimCount) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800555 StkAppInstaller.unInstall(mContext);
556 }
557 break;
558 case OP_DELAYED_MSG:
Wink Savillee68857d2014-10-17 15:23:05 -0700559 handleDelayedCmd(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800560 break;
Wink Saville94e982b2014-07-11 07:38:14 -0700561 case OP_CARD_STATUS_CHANGED:
Wink Savillee68857d2014-10-17 15:23:05 -0700562 CatLog.d(LOG_TAG, "Card/Icc Status change received");
563 handleCardStatusChangeAndIccRefresh((Bundle) msg.obj, slotId);
564 break;
565 case OP_SET_ACT_INST:
566 Activity act = new Activity();
567 act = (Activity) msg.obj;
568 CatLog.d(LOG_TAG, "Set activity instance. " + act);
569 mStkContext[slotId].mActivityInstance = act;
570 break;
571 case OP_SET_DAL_INST:
572 Activity dal = new Activity();
573 CatLog.d(LOG_TAG, "Set dialog instance. " + dal);
574 dal = (Activity) msg.obj;
575 mStkContext[slotId].mDialogInstance = dal;
576 break;
577 case OP_SET_MAINACT_INST:
578 Activity mainAct = new Activity();
579 mainAct = (Activity) msg.obj;
580 CatLog.d(LOG_TAG, "Set activity instance. " + mainAct);
581 mStkContext[slotId].mMainActivityInstance = mainAct;
Wink Saville94e982b2014-07-11 07:38:14 -0700582 break;
Preeti Ahuja95919342013-10-01 18:18:55 -0700583 case OP_LOCALE_CHANGED:
584 CatLog.d(this, "Locale Changed");
Yuta Ui1481b172016-02-03 15:34:31 +0900585 for (int slot = PhoneConstants.SIM_ID_1; slot < mSimCount; slot++) {
586 checkForSetupEvent(LANGUAGE_SELECTION_EVENT, (Bundle) msg.obj, slot);
587 }
Preeti Ahuja95919342013-10-01 18:18:55 -0700588 break;
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +0530589 case OP_ALPHA_NOTIFY:
590 handleAlphaNotify((Bundle) msg.obj);
591 break;
Preeti Ahuja560be362014-11-25 19:38:24 -0800592 case OP_IDLE_SCREEN:
593 for (int slot = 0; slot < mSimCount; slot++) {
594 if (mStkContext[slot] != null) {
595 handleIdleScreen(slot);
596 }
597 }
598 break;
Wink Saville94e982b2014-07-11 07:38:14 -0700599 }
600 }
601
Wink Savillee68857d2014-10-17 15:23:05 -0700602 private void handleCardStatusChangeAndIccRefresh(Bundle args, int slotId) {
Wink Saville94e982b2014-07-11 07:38:14 -0700603 boolean cardStatus = args.getBoolean(AppInterface.CARD_STATUS);
604
Wink Savillee68857d2014-10-17 15:23:05 -0700605 CatLog.d(LOG_TAG, "CardStatus: " + cardStatus);
Wink Saville94e982b2014-07-11 07:38:14 -0700606 if (cardStatus == false) {
Wink Savillee68857d2014-10-17 15:23:05 -0700607 CatLog.d(LOG_TAG, "CARD is ABSENT");
Wink Saville94e982b2014-07-11 07:38:14 -0700608 // Uninstall STKAPP, Clear Idle text, Stop StkAppService
Wink Savillee68857d2014-10-17 15:23:05 -0700609 mNotificationManager.cancel(getNotificationId(slotId));
Srikanth Chintala7c5a04c2016-09-22 19:05:01 +0530610 mStkContext[slotId].mCurrentMenu = null;
611 mStkContext[slotId].mMainCmd = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700612 if (isAllOtherCardsAbsent(slotId)) {
613 CatLog.d(LOG_TAG, "All CARDs are ABSENT");
614 StkAppInstaller.unInstall(mContext);
615 stopSelf();
616 }
Wink Saville94e982b2014-07-11 07:38:14 -0700617 } else {
618 IccRefreshResponse state = new IccRefreshResponse();
619 state.refreshResult = args.getInt(AppInterface.REFRESH_RESULT);
620
Wink Savillee68857d2014-10-17 15:23:05 -0700621 CatLog.d(LOG_TAG, "Icc Refresh Result: "+ state.refreshResult);
Wink Saville94e982b2014-07-11 07:38:14 -0700622 if ((state.refreshResult == IccRefreshResponse.REFRESH_RESULT_INIT) ||
623 (state.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET)) {
624 // Clear Idle Text
Wink Savillee68857d2014-10-17 15:23:05 -0700625 mNotificationManager.cancel(getNotificationId(slotId));
Wink Saville94e982b2014-07-11 07:38:14 -0700626 }
627
628 if (state.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET) {
629 // Uninstall STkmenu
Wink Savillee68857d2014-10-17 15:23:05 -0700630 if (isAllOtherCardsAbsent(slotId)) {
631 StkAppInstaller.unInstall(mContext);
632 }
633 mStkContext[slotId].mCurrentMenu = null;
634 mStkContext[slotId].mMainCmd = null;
Wink Saville94e982b2014-07-11 07:38:14 -0700635 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800636 }
637 }
638 }
Wink Savillee68857d2014-10-17 15:23:05 -0700639 /*
640 * Check if all SIMs are absent except the id of slot equals "slotId".
641 */
642 private boolean isAllOtherCardsAbsent(int slotId) {
643 TelephonyManager mTm = (TelephonyManager) mContext.getSystemService(
644 Context.TELEPHONY_SERVICE);
645 int i = 0;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800646
Wink Savillee68857d2014-10-17 15:23:05 -0700647 for (i = 0; i < mSimCount; i++) {
648 if (i != slotId && mTm.hasIccCard(i)) {
649 break;
650 }
651 }
652 if (i == mSimCount) {
653 return true;
654 } else {
655 return false;
656 }
657 }
Preeti Ahuja95919342013-10-01 18:18:55 -0700658
Preeti Ahuja560be362014-11-25 19:38:24 -0800659 /*
660 * If the device is not in an interactive state, we can assume
661 * that the screen is idle.
662 */
663 private boolean isScreenIdle() {
664 return (!mPowerManager.isInteractive());
665 }
666
667 private void handleIdleScreen(int slotId) {
668
669 // If the idle screen event is present in the list need to send the
670 // response to SIM.
671 CatLog.d(this, "Need to send IDLE SCREEN Available event to SIM");
672 checkForSetupEvent(IDLE_SCREEN_AVAILABLE_EVENT, null, slotId);
673
674 if (mStkContext[slotId].mIdleModeTextCmd != null) {
675 launchIdleText(slotId);
676 }
677 }
678
679 private void sendScreenBusyResponse(int slotId) {
680 if (mStkContext[slotId].mCurrentCmd == null) {
681 return;
682 }
683 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentCmd);
684 CatLog.d(this, "SCREEN_BUSY");
685 resMsg.setResultCode(ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS);
686 mStkService[slotId].onCmdResponse(resMsg);
687 if (mStkContext[slotId].mCmdsQ.size() != 0) {
688 callDelayedMsg(slotId);
689 } else {
690 mStkContext[slotId].mCmdInProgress = false;
691 }
692 }
693
Preeti Ahuja95919342013-10-01 18:18:55 -0700694 private void sendResponse(int resId, int slotId, boolean confirm) {
695 Message msg = mServiceHandler.obtainMessage();
696 msg.arg1 = OP_RESPONSE;
Takanori Nakano49b12722016-02-16 14:34:14 +0900697 msg.arg2 = slotId;
Preeti Ahuja95919342013-10-01 18:18:55 -0700698 Bundle args = new Bundle();
699 args.putInt(StkAppService.RES_ID, resId);
Preeti Ahuja95919342013-10-01 18:18:55 -0700700 args.putBoolean(StkAppService.CONFIRMATION, confirm);
701 msg.obj = args;
702 mServiceHandler.sendMessage(msg);
703 }
704
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700705 private boolean isCmdInteractive(CatCmdMessage cmd) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800706 switch (cmd.getCmdType()) {
707 case SEND_DTMF:
708 case SEND_SMS:
709 case SEND_SS:
710 case SEND_USSD:
711 case SET_UP_IDLE_MODE_TEXT:
712 case SET_UP_MENU:
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500713 case CLOSE_CHANNEL:
714 case RECEIVE_DATA:
715 case SEND_DATA:
Preeti Ahuja95919342013-10-01 18:18:55 -0700716 case SET_UP_EVENT_LIST:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800717 return false;
718 }
719
720 return true;
721 }
722
Wink Savillee68857d2014-10-17 15:23:05 -0700723 private void handleDelayedCmd(int slotId) {
724 CatLog.d(LOG_TAG, "handleDelayedCmd, slotId: " + slotId);
725 if (mStkContext[slotId].mCmdsQ.size() != 0) {
726 DelayedCmd cmd = mStkContext[slotId].mCmdsQ.poll();
727 if (cmd != null) {
728 CatLog.d(LOG_TAG, "handleDelayedCmd - queue size: " +
729 mStkContext[slotId].mCmdsQ.size() +
730 " id: " + cmd.id + "sim id: " + cmd.slotId);
731 switch (cmd.id) {
732 case OP_CMD:
733 handleCmd(cmd.msg, cmd.slotId);
734 break;
735 case OP_END_SESSION:
736 handleSessionEnd(cmd.slotId);
737 break;
738 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800739 }
740 }
741 }
742
Wink Savillee68857d2014-10-17 15:23:05 -0700743 private void callDelayedMsg(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800744 Message msg = mServiceHandler.obtainMessage();
745 msg.arg1 = OP_DELAYED_MSG;
Wink Savillee68857d2014-10-17 15:23:05 -0700746 msg.arg2 = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800747 mServiceHandler.sendMessage(msg);
748 }
749
Wink Savillee68857d2014-10-17 15:23:05 -0700750 private void callSetActivityInstMsg(int inst_type, int slotId, Object obj) {
751 Message msg = mServiceHandler.obtainMessage();
752 msg.obj = obj;
753 msg.arg1 = inst_type;
754 msg.arg2 = slotId;
755 mServiceHandler.sendMessage(msg);
756 }
757
758 private void handleSessionEnd(int slotId) {
Legler Wuaeefef52014-10-27 00:57:18 +0800759 // We should finish all pending activity if receiving END SESSION command.
760 cleanUpInstanceStackBySlot(slotId);
761
Wink Savillee68857d2014-10-17 15:23:05 -0700762 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
763 CatLog.d(LOG_TAG, "[handleSessionEnd] - mCurrentCmd changed to mMainCmd!.");
764 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mMainCmd;
765 CatLog.d(LOG_TAG, "slotId: " + slotId + ", mMenuState: " +
766 mStkContext[slotId].mMenuState);
767
768 mStkContext[slotId].mIsInputPending = false;
769 mStkContext[slotId].mIsMenuPending = false;
770 mStkContext[slotId].mIsDialogPending = false;
771
Wink Savillee68857d2014-10-17 15:23:05 -0700772 if (mStkContext[slotId].mMainCmd == null) {
773 CatLog.d(LOG_TAG, "[handleSessionEnd][mMainCmd is null!]");
774 }
775 mStkContext[slotId].lastSelectedItem = null;
Wink Saville79085fc2009-06-09 10:27:23 -0700776 // In case of SET UP MENU command which removed the app, don't
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800777 // update the current menu member.
Wink Savillee68857d2014-10-17 15:23:05 -0700778 if (mStkContext[slotId].mCurrentMenu != null && mStkContext[slotId].mMainCmd != null) {
779 mStkContext[slotId].mCurrentMenu = mStkContext[slotId].mMainCmd.getMenu();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800780 }
Wink Savillee68857d2014-10-17 15:23:05 -0700781 CatLog.d(LOG_TAG, "[handleSessionEnd][mMenuState]" + mStkContext[slotId].mMenuIsVisible);
782 // In mutiple instance architecture, the main menu for slotId will be finished when user
783 // goes to the Stk menu of the other SIM. So, we should launch a new instance for the
784 // main menu if the main menu instance has been finished.
785 // If the current menu is secondary menu, we should launch main menu.
786 if (StkMenuActivity.STATE_SECONDARY == mStkContext[slotId].mMenuState) {
787 launchMenuActivity(null, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800788 }
Wink Savillee68857d2014-10-17 15:23:05 -0700789 if (mStkContext[slotId].mCmdsQ.size() != 0) {
790 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800791 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700792 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800793 }
794 // In case a launch browser command was just confirmed, launch that url.
Wink Savillee68857d2014-10-17 15:23:05 -0700795 if (mStkContext[slotId].launchBrowser) {
796 mStkContext[slotId].launchBrowser = false;
797 launchBrowser(mStkContext[slotId].mBrowserSettings);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800798 }
799 }
800
Preeti Ahuja560be362014-11-25 19:38:24 -0800801 // returns true if any Stk related activity already has focus on the screen
802 private boolean isTopOfStack() {
pkanwareab12f32017-02-06 08:35:03 -0800803 ActivityManager mActivityManager = (ActivityManager) mContext
Preeti Ahuja560be362014-11-25 19:38:24 -0800804 .getSystemService(ACTIVITY_SERVICE);
pkanwareab12f32017-02-06 08:35:03 -0800805 String currentPackageName = null;
806 List<RunningTaskInfo> tasks = mActivityManager.getRunningTasks(1);
807 if (tasks == null || tasks.get(0).topActivity == null) {
808 return false;
809 }
810 currentPackageName = tasks.get(0).topActivity.getPackageName();
Preeti Ahuja560be362014-11-25 19:38:24 -0800811 if (null != currentPackageName) {
812 return currentPackageName.equals(PACKAGE_NAME);
813 }
Preeti Ahuja560be362014-11-25 19:38:24 -0800814 return false;
815 }
816
Wink Savillee68857d2014-10-17 15:23:05 -0700817 private void handleCmd(CatCmdMessage cmdMsg, int slotId) {
Preeti Ahuja95919342013-10-01 18:18:55 -0700818
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800819 if (cmdMsg == null) {
820 return;
821 }
822 // save local reference for state tracking.
Wink Savillee68857d2014-10-17 15:23:05 -0700823 mStkContext[slotId].mCurrentCmd = cmdMsg;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800824 boolean waitForUsersResponse = true;
825
Wink Savillee68857d2014-10-17 15:23:05 -0700826 mStkContext[slotId].mIsInputPending = false;
827 mStkContext[slotId].mIsMenuPending = false;
828 mStkContext[slotId].mIsDialogPending = false;
829
830 CatLog.d(LOG_TAG,"[handleCmd]" + cmdMsg.getCmdType().name());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800831 switch (cmdMsg.getCmdType()) {
832 case DISPLAY_TEXT:
833 TextMessage msg = cmdMsg.geTextMessage();
Jeevaka Badrappan854a25c2012-12-01 16:32:03 +0200834 waitForUsersResponse = msg.responseNeeded;
Wink Savillee68857d2014-10-17 15:23:05 -0700835 if (mStkContext[slotId].lastSelectedItem != null) {
836 msg.title = mStkContext[slotId].lastSelectedItem;
837 } else if (mStkContext[slotId].mMainCmd != null){
838 msg.title = mStkContext[slotId].mMainCmd.getMenu().title;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800839 } else {
840 // TODO: get the carrier name from the SIM
841 msg.title = "";
842 }
Preeti Ahuja560be362014-11-25 19:38:24 -0800843 //If we receive a low priority Display Text and the device is
844 // not displaying any STK related activity and the screen is not idle
845 // ( that is, device is in an interactive state), then send a screen busy
846 // terminal response. Otherwise display the message. The existing
847 // displayed message shall be updated with the new display text
848 // proactive command (Refer to ETSI TS 102 384 section 27.22.4.1.4.4.2).
849 if (!(msg.isHighPriority || mStkContext[slotId].mMenuIsVisible
850 || mStkContext[slotId].mDisplayTextDlgIsVisibile || isTopOfStack())) {
851 if(!isScreenIdle()) {
852 CatLog.d(LOG_TAG, "Screen is not idle");
853 sendScreenBusyResponse(slotId);
854 } else {
855 launchTextDialog(slotId);
856 }
857 } else {
858 launchTextDialog(slotId);
859 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800860 break;
861 case SELECT_ITEM:
Wink Savillee68857d2014-10-17 15:23:05 -0700862 CatLog.d(LOG_TAG, "SELECT_ITEM +");
863 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
864 mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
865 launchMenuActivity(cmdMsg.getMenu(), slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800866 break;
867 case SET_UP_MENU:
Wink Savillee68857d2014-10-17 15:23:05 -0700868 mStkContext[slotId].mCmdInProgress = false;
869 mStkContext[slotId].mMainCmd = mStkContext[slotId].mCurrentCmd;
870 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
871 mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
872 CatLog.d(LOG_TAG, "SET_UP_MENU [" + removeMenu(slotId) + "]");
873
874 if (removeMenu(slotId)) {
875 int i = 0;
876 CatLog.d(LOG_TAG, "removeMenu() - Uninstall App");
877 mStkContext[slotId].mCurrentMenu = null;
Preeti Ahuja95919342013-10-01 18:18:55 -0700878 mStkContext[slotId].mMainCmd = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700879 //Check other setup menu state. If all setup menu are removed, uninstall apk.
880 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
881 if (i != slotId
882 && (mStkContext[slotId].mSetupMenuState == STATE_UNKNOWN
883 || mStkContext[slotId].mSetupMenuState == STATE_EXIST)) {
884 CatLog.d(LOG_TAG, "Not Uninstall App:" + i + ","
885 + mStkContext[slotId].mSetupMenuState);
886 break;
887 }
888 }
889 if (i == mSimCount) {
890 StkAppInstaller.unInstall(mContext);
891 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800892 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700893 CatLog.d(LOG_TAG, "install App");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800894 StkAppInstaller.install(mContext);
895 }
Wink Savillee68857d2014-10-17 15:23:05 -0700896 if (mStkContext[slotId].mMenuIsVisible) {
897 launchMenuActivity(null, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800898 }
899 break;
900 case GET_INPUT:
901 case GET_INKEY:
Wink Savillee68857d2014-10-17 15:23:05 -0700902 launchInputActivity(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800903 break;
904 case SET_UP_IDLE_MODE_TEXT:
905 waitForUsersResponse = false;
Preeti Ahuja560be362014-11-25 19:38:24 -0800906 mStkContext[slotId].mIdleModeTextCmd = mStkContext[slotId].mCurrentCmd;
907 TextMessage idleModeText = mStkContext[slotId].mCurrentCmd.geTextMessage();
908 if (idleModeText == null) {
909 launchIdleText(slotId);
910 mStkContext[slotId].mIdleModeTextCmd = null;
911 }
912 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
913 if ((mStkContext[slotId].mIdleModeTextCmd != null) && isScreenIdle()) {
914 CatLog.d(this, "set up idle mode");
915 launchIdleText(slotId);
916 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800917 break;
918 case SEND_DTMF:
919 case SEND_SMS:
920 case SEND_SS:
921 case SEND_USSD:
Preeti Ahuja95919342013-10-01 18:18:55 -0700922 case GET_CHANNEL_STATUS:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800923 waitForUsersResponse = false;
Wink Savillee68857d2014-10-17 15:23:05 -0700924 launchEventMessage(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800925 break;
926 case LAUNCH_BROWSER:
Ryuto Sawada0bdc7192016-04-18 12:10:56 +0900927 // The device setup process should not be interrupted by launching browser.
928 if (Settings.Global.getInt(mContext.getContentResolver(),
929 Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
930 CatLog.d(this, "The command is not performed if the setup has not been completed.");
931 sendScreenBusyResponse(slotId);
932 break;
933 }
Preeti Ahujaa7cdca22013-10-01 18:20:56 -0700934 TextMessage alphaId = mStkContext[slotId].mCurrentCmd.geTextMessage();
935 if ((mStkContext[slotId].mCurrentCmd.getBrowserSettings().mode
936 == LaunchBrowserMode.LAUNCH_IF_NOT_ALREADY_LAUNCHED) &&
937 ((alphaId == null) || TextUtils.isEmpty(alphaId.text))) {
938 // don't need user confirmation in this case
939 // just launch the browser or spawn a new tab
940 CatLog.d(this, "Browser mode is: launch if not already launched " +
941 "and user confirmation is not currently needed.\n" +
942 "supressing confirmation dialogue and confirming silently...");
943 mStkContext[slotId].launchBrowser = true;
944 mStkContext[slotId].mBrowserSettings =
945 mStkContext[slotId].mCurrentCmd.getBrowserSettings();
946 sendResponse(RES_ID_CONFIRM, slotId, true);
947 } else {
948 launchConfirmationDialog(alphaId, slotId);
949 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800950 break;
951 case SET_UP_CALL:
Preeti Ahujadd240102013-08-30 17:25:06 -0700952 TextMessage mesg = mStkContext[slotId].mCurrentCmd.getCallSettings().confirmMsg;
953 if((mesg != null) && (mesg.text == null || mesg.text.length() == 0)) {
954 mesg.text = getResources().getString(R.string.default_setup_call_msg);
955 }
956 CatLog.d(this, "SET_UP_CALL mesg.text " + mesg.text);
957 launchConfirmationDialog(mesg, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800958 break;
959 case PLAY_TONE:
Wink Savillee68857d2014-10-17 15:23:05 -0700960 launchToneDialog(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800961 break;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500962 case OPEN_CHANNEL:
Wink Savillee68857d2014-10-17 15:23:05 -0700963 launchOpenChannelDialog(slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500964 break;
965 case CLOSE_CHANNEL:
966 case RECEIVE_DATA:
967 case SEND_DATA:
Wink Savillee68857d2014-10-17 15:23:05 -0700968 TextMessage m = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500969
970 if ((m != null) && (m.text == null)) {
971 switch(cmdMsg.getCmdType()) {
972 case CLOSE_CHANNEL:
973 m.text = getResources().getString(R.string.default_close_channel_msg);
974 break;
975 case RECEIVE_DATA:
976 m.text = getResources().getString(R.string.default_receive_data_msg);
977 break;
978 case SEND_DATA:
979 m.text = getResources().getString(R.string.default_send_data_msg);
980 break;
981 }
982 }
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -0700983 /*
984 * Display indication in the form of a toast to the user if required.
985 */
Wink Savillee68857d2014-10-17 15:23:05 -0700986 launchEventMessage(slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500987 break;
Preeti Ahuja95919342013-10-01 18:18:55 -0700988 case SET_UP_EVENT_LIST:
989 mStkContext[slotId].mSetupEventListSettings =
990 mStkContext[slotId].mCurrentCmd.getSetEventList();
991 mStkContext[slotId].mCurrentSetupEventCmd = mStkContext[slotId].mCurrentCmd;
992 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
Preeti Ahuja560be362014-11-25 19:38:24 -0800993 if (isScreenIdle()) {
994 CatLog.d(this," Check if IDLE_SCREEN_AVAILABLE_EVENT is present in List");
995 checkForSetupEvent(IDLE_SCREEN_AVAILABLE_EVENT, null, slotId);
996 }
Preeti Ahuja95919342013-10-01 18:18:55 -0700997 break;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800998 }
999
1000 if (!waitForUsersResponse) {
Wink Savillee68857d2014-10-17 15:23:05 -07001001 if (mStkContext[slotId].mCmdsQ.size() != 0) {
1002 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001003 } else {
Wink Savillee68857d2014-10-17 15:23:05 -07001004 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001005 }
1006 }
1007 }
1008
Wink Savillee68857d2014-10-17 15:23:05 -07001009 private void handleCmdResponse(Bundle args, int slotId) {
1010 CatLog.d(LOG_TAG, "handleCmdResponse, sim id: " + slotId);
1011 if (mStkContext[slotId].mCurrentCmd == null) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001012 return;
1013 }
Wink Savillee68857d2014-10-17 15:23:05 -07001014
1015 if (mStkService[slotId] == null) {
Legler Wuaeefef52014-10-27 00:57:18 +08001016 mStkService[slotId] = CatService.getInstance(slotId);
Wink Savillee68857d2014-10-17 15:23:05 -07001017 if (mStkService[slotId] == null) {
Alex Yakavenkad8e2ecd2012-04-20 17:10:15 -07001018 // This should never happen (we should be responding only to a message
1019 // that arrived from StkService). It has to exist by this time
Wink Savillee68857d2014-10-17 15:23:05 -07001020 CatLog.d(LOG_TAG, "Exception! mStkService is null when we need to send response.");
Alex Yakavenkad8e2ecd2012-04-20 17:10:15 -07001021 throw new RuntimeException("mStkService is null when we need to send response");
1022 }
1023 }
1024
Wink Savillee68857d2014-10-17 15:23:05 -07001025 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentCmd);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001026
1027 // set result code
1028 boolean helpRequired = args.getBoolean(HELP, false);
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001029 boolean confirmed = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001030
1031 switch(args.getInt(RES_ID)) {
1032 case RES_ID_MENU_SELECTION:
Wink Savillee68857d2014-10-17 15:23:05 -07001033 CatLog.d(LOG_TAG, "MENU_SELECTION=" + mStkContext[slotId].
1034 mCurrentMenuCmd.getCmdType());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001035 int menuSelection = args.getInt(MENU_SELECTION);
Wink Savillee68857d2014-10-17 15:23:05 -07001036 switch(mStkContext[slotId].mCurrentMenuCmd.getCmdType()) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001037 case SET_UP_MENU:
1038 case SELECT_ITEM:
Wink Savillee68857d2014-10-17 15:23:05 -07001039 mStkContext[slotId].lastSelectedItem = getItemName(menuSelection, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001040 if (helpRequired) {
1041 resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
1042 } else {
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301043 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1044 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001045 }
1046 resMsg.setMenuSelection(menuSelection);
1047 break;
1048 }
1049 break;
1050 case RES_ID_INPUT:
Wink Savillee68857d2014-10-17 15:23:05 -07001051 CatLog.d(LOG_TAG, "RES_ID_INPUT");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001052 String input = args.getString(INPUT);
Wink Savillee68857d2014-10-17 15:23:05 -07001053 if (input != null && (null != mStkContext[slotId].mCurrentCmd.geInput()) &&
1054 (mStkContext[slotId].mCurrentCmd.geInput().yesNo)) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001055 boolean yesNoSelection = input
1056 .equals(StkInputActivity.YES_STR_RESPONSE);
1057 resMsg.setYesNo(yesNoSelection);
1058 } else {
1059 if (helpRequired) {
1060 resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
1061 } else {
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301062 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1063 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001064 resMsg.setInput(input);
1065 }
1066 }
1067 break;
1068 case RES_ID_CONFIRM:
Alex Yakavenkad41f1d92010-07-12 14:13:13 -07001069 CatLog.d(this, "RES_ID_CONFIRM");
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001070 confirmed = args.getBoolean(CONFIRMATION);
Wink Savillee68857d2014-10-17 15:23:05 -07001071 switch (mStkContext[slotId].mCurrentCmd.getCmdType()) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001072 case DISPLAY_TEXT:
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301073 if (confirmed) {
1074 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1075 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
1076 } else {
1077 resMsg.setResultCode(ResultCode.UICC_SESSION_TERM_BY_USER);
1078 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001079 break;
1080 case LAUNCH_BROWSER:
1081 resMsg.setResultCode(confirmed ? ResultCode.OK
1082 : ResultCode.UICC_SESSION_TERM_BY_USER);
1083 if (confirmed) {
Wink Savillee68857d2014-10-17 15:23:05 -07001084 mStkContext[slotId].launchBrowser = true;
1085 mStkContext[slotId].mBrowserSettings =
1086 mStkContext[slotId].mCurrentCmd.getBrowserSettings();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001087 }
1088 break;
1089 case SET_UP_CALL:
1090 resMsg.setResultCode(ResultCode.OK);
1091 resMsg.setConfirmation(confirmed);
1092 if (confirmed) {
Wink Savillee68857d2014-10-17 15:23:05 -07001093 launchEventMessage(slotId,
1094 mStkContext[slotId].mCurrentCmd.getCallSettings().callMsg);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001095 }
1096 break;
1097 }
1098 break;
1099 case RES_ID_DONE:
1100 resMsg.setResultCode(ResultCode.OK);
1101 break;
1102 case RES_ID_BACKWARD:
Wink Savillee68857d2014-10-17 15:23:05 -07001103 CatLog.d(LOG_TAG, "RES_ID_BACKWARD");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001104 resMsg.setResultCode(ResultCode.BACKWARD_MOVE_BY_USER);
1105 break;
1106 case RES_ID_END_SESSION:
Wink Savillee68857d2014-10-17 15:23:05 -07001107 CatLog.d(LOG_TAG, "RES_ID_END_SESSION");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001108 resMsg.setResultCode(ResultCode.UICC_SESSION_TERM_BY_USER);
1109 break;
1110 case RES_ID_TIMEOUT:
Wink Savillee68857d2014-10-17 15:23:05 -07001111 CatLog.d(LOG_TAG, "RES_ID_TIMEOUT");
Naveen Kallad5176892009-11-30 12:45:29 -08001112 // GCF test-case 27.22.4.1.1 Expected Sequence 1.5 (DISPLAY TEXT,
1113 // Clear message after delay, successful) expects result code OK.
1114 // If the command qualifier specifies no user response is required
1115 // then send OK instead of NO_RESPONSE_FROM_USER
Wink Savillee68857d2014-10-17 15:23:05 -07001116 if ((mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1117 AppInterface.CommandType.DISPLAY_TEXT.value())
1118 && (mStkContext[slotId].mCurrentCmd.geTextMessage().userClear == false)) {
Naveen Kallad5176892009-11-30 12:45:29 -08001119 resMsg.setResultCode(ResultCode.OK);
1120 } else {
1121 resMsg.setResultCode(ResultCode.NO_RESPONSE_FROM_USER);
1122 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001123 break;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001124 case RES_ID_CHOICE:
1125 int choice = args.getInt(CHOICE);
1126 CatLog.d(this, "User Choice=" + choice);
1127 switch (choice) {
1128 case YES:
1129 resMsg.setResultCode(ResultCode.OK);
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001130 confirmed = true;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001131 break;
1132 case NO:
1133 resMsg.setResultCode(ResultCode.USER_NOT_ACCEPT);
1134 break;
1135 }
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001136
Wink Savillee68857d2014-10-17 15:23:05 -07001137 if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1138 AppInterface.CommandType.OPEN_CHANNEL.value()) {
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001139 resMsg.setConfirmation(confirmed);
1140 }
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001141 break;
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001142
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001143 default:
Wink Savillee68857d2014-10-17 15:23:05 -07001144 CatLog.d(LOG_TAG, "Unknown result id");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001145 return;
1146 }
Wink Savillee68857d2014-10-17 15:23:05 -07001147
1148 if (null != mStkContext[slotId].mCurrentCmd &&
1149 null != mStkContext[slotId].mCurrentCmd.getCmdType()) {
1150 CatLog.d(LOG_TAG, "handleCmdResponse- cmdName[" +
1151 mStkContext[slotId].mCurrentCmd.getCmdType().name() + "]");
1152 }
1153 mStkService[slotId].onCmdResponse(resMsg);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001154 }
1155
1156 /**
1157 * Returns 0 or FLAG_ACTIVITY_NO_USER_ACTION, 0 means the user initiated the action.
1158 *
1159 * @param userAction If the userAction is yes then we always return 0 otherwise
1160 * mMenuIsVisible is used to determine what to return. If mMenuIsVisible is true
1161 * then we are the foreground app and we'll return 0 as from our perspective a
1162 * user action did cause. If it's false than we aren't the foreground app and
1163 * FLAG_ACTIVITY_NO_USER_ACTION is returned.
Wink Saville79085fc2009-06-09 10:27:23 -07001164 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001165 * @return 0 or FLAG_ACTIVITY_NO_USER_ACTION
1166 */
Wink Savillee68857d2014-10-17 15:23:05 -07001167 private int getFlagActivityNoUserAction(InitiatedByUserAction userAction, int slotId) {
1168 return ((userAction == InitiatedByUserAction.yes) | mStkContext[slotId].mMenuIsVisible)
1169 ? 0 : Intent.FLAG_ACTIVITY_NO_USER_ACTION;
1170 }
1171 /**
1172 * This method is used for cleaning up pending instances in stack.
1173 */
1174 private void cleanUpInstanceStackBySlot(int slotId) {
1175 Activity activity = mStkContext[slotId].getPendingActivityInstance();
1176 Activity dialog = mStkContext[slotId].getPendingDialogInstance();
1177 CatLog.d(LOG_TAG, "cleanUpInstanceStackBySlot slotId: " + slotId);
Legler Wuaeefef52014-10-27 00:57:18 +08001178 if (mStkContext[slotId].mCurrentCmd == null) {
1179 CatLog.d(LOG_TAG, "current cmd is null.");
1180 return;
1181 }
Wink Savillee68857d2014-10-17 15:23:05 -07001182 if (activity != null) {
1183 CatLog.d(LOG_TAG, "current cmd type: " +
1184 mStkContext[slotId].mCurrentCmd.getCmdType());
1185 if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1186 AppInterface.CommandType.GET_INPUT.value() ||
1187 mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1188 AppInterface.CommandType.GET_INKEY.value()) {
1189 mStkContext[slotId].mIsInputPending = true;
1190 } else if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1191 AppInterface.CommandType.SET_UP_MENU.value() ||
1192 mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1193 AppInterface.CommandType.SELECT_ITEM.value()) {
1194 mStkContext[slotId].mIsMenuPending = true;
1195 } else {
1196 }
1197 CatLog.d(LOG_TAG, "finish pending activity.");
1198 activity.finish();
1199 mStkContext[slotId].mActivityInstance = null;
1200 }
1201 if (dialog != null) {
1202 CatLog.d(LOG_TAG, "finish pending dialog.");
1203 mStkContext[slotId].mIsDialogPending = true;
1204 dialog.finish();
1205 mStkContext[slotId].mDialogInstance = null;
1206 }
1207 }
1208 /**
1209 * This method is used for restoring pending instances from stack.
1210 */
1211 private void restoreInstanceFromStackBySlot(int slotId) {
1212 AppInterface.CommandType cmdType = mStkContext[slotId].mCurrentCmd.getCmdType();
1213
1214 CatLog.d(LOG_TAG, "restoreInstanceFromStackBySlot cmdType : " + cmdType);
1215 switch(cmdType) {
1216 case GET_INPUT:
1217 case GET_INKEY:
1218 launchInputActivity(slotId);
1219 //Set mMenuIsVisible to true for showing main menu for
1220 //following session end command.
1221 mStkContext[slotId].mMenuIsVisible = true;
1222 break;
1223 case DISPLAY_TEXT:
1224 launchTextDialog(slotId);
1225 break;
1226 case LAUNCH_BROWSER:
1227 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.geTextMessage(),
1228 slotId);
1229 break;
1230 case OPEN_CHANNEL:
1231 launchOpenChannelDialog(slotId);
1232 break;
1233 case SET_UP_CALL:
1234 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.getCallSettings().
1235 confirmMsg, slotId);
1236 break;
1237 case SET_UP_MENU:
1238 case SELECT_ITEM:
1239 launchMenuActivity(null, slotId);
1240 break;
1241 default:
1242 break;
1243 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001244 }
1245
Wink Savillee68857d2014-10-17 15:23:05 -07001246 private void launchMenuActivity(Menu menu, int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001247 Intent newIntent = new Intent(Intent.ACTION_VIEW);
Wink Savillee68857d2014-10-17 15:23:05 -07001248 String targetActivity = STK_MENU_ACTIVITY_NAME;
1249 String uriString = STK_MENU_URI + System.currentTimeMillis();
1250 //Set unique URI to create a new instance of activity for different slotId.
1251 Uri uriData = Uri.parse(uriString);
1252
1253 CatLog.d(LOG_TAG, "launchMenuActivity, slotId: " + slotId + " , " +
1254 uriData.toString() + " , " + mStkContext[slotId].mOpCode + ", "
1255 + mStkContext[slotId].mMenuState);
1256 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1257 int intentFlags = Intent.FLAG_ACTIVITY_NEW_TASK;
1258
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001259 if (menu == null) {
1260 // We assume this was initiated by the user pressing the tool kit icon
Wink Savillee68857d2014-10-17 15:23:05 -07001261 intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.yes, slotId);
1262 if (mStkContext[slotId].mOpCode == OP_END_SESSION) {
1263 CatLog.d(LOG_TAG, "launchMenuActivity, return OP_END_SESSION");
1264 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
1265 if (mStkContext[slotId].mMainActivityInstance != null) {
1266 CatLog.d(LOG_TAG, "launchMenuActivity, mMainActivityInstance is not null");
1267 return;
1268 }
Wink Savillee68857d2014-10-17 15:23:05 -07001269 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001270
Wink Savillee68857d2014-10-17 15:23:05 -07001271 //If the last pending menu is secondary menu, "STATE" should be "STATE_SECONDARY".
1272 //Otherwise, it should be "STATE_MAIN".
1273 if (mStkContext[slotId].mOpCode == OP_LAUNCH_APP &&
1274 mStkContext[slotId].mMenuState == StkMenuActivity.STATE_SECONDARY) {
1275 newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
1276 } else {
1277 newIntent.putExtra("STATE", StkMenuActivity.STATE_MAIN);
1278 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
1279 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001280 } else {
1281 // We don't know and we'll let getFlagActivityNoUserAction decide.
Wink Savillee68857d2014-10-17 15:23:05 -07001282 intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001283 newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
Wink Savillee68857d2014-10-17 15:23:05 -07001284 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_SECONDARY;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001285 }
Wink Savillee68857d2014-10-17 15:23:05 -07001286 newIntent.putExtra(SLOT_ID, slotId);
1287 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001288 newIntent.setFlags(intentFlags);
1289 mContext.startActivity(newIntent);
1290 }
1291
Wink Savillee68857d2014-10-17 15:23:05 -07001292 private void launchInputActivity(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001293 Intent newIntent = new Intent(Intent.ACTION_VIEW);
Wink Savillee68857d2014-10-17 15:23:05 -07001294 String targetActivity = STK_INPUT_ACTIVITY_NAME;
1295 String uriString = STK_INPUT_URI + System.currentTimeMillis();
1296 //Set unique URI to create a new instance of activity for different slotId.
1297 Uri uriData = Uri.parse(uriString);
1298
1299 CatLog.d(LOG_TAG, "launchInputActivity, slotId: " + slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001300 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
Wink Savillee68857d2014-10-17 15:23:05 -07001301 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1302 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1303 newIntent.putExtra("INPUT", mStkContext[slotId].mCurrentCmd.geInput());
1304 newIntent.putExtra(SLOT_ID, slotId);
1305 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001306 mContext.startActivity(newIntent);
1307 }
1308
Wink Savillee68857d2014-10-17 15:23:05 -07001309 private void launchTextDialog(int slotId) {
1310 CatLog.d(LOG_TAG, "launchTextDialog, slotId: " + slotId);
1311 Intent newIntent = new Intent();
1312 String targetActivity = STK_DIALOG_ACTIVITY_NAME;
1313 int action = getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
1314 String uriString = STK_DIALOG_URI + System.currentTimeMillis();
1315 //Set unique URI to create a new instance of activity for different slotId.
1316 Uri uriData = Uri.parse(uriString);
1317 if (newIntent != null) {
1318 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1319 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1320 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
1321 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1322 newIntent.setData(uriData);
1323 newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
1324 newIntent.putExtra(SLOT_ID, slotId);
1325 startActivity(newIntent);
Preeti Ahuja414bc412013-06-25 19:31:49 -07001326 // For display texts with immediate response, send the terminal response
1327 // immediately. responseNeeded will be false, if display text command has
1328 // the immediate response tlv.
1329 if (!mStkContext[slotId].mCurrentCmd.geTextMessage().responseNeeded) {
1330 sendResponse(RES_ID_CONFIRM, slotId, true);
1331 }
Wink Savillee68857d2014-10-17 15:23:05 -07001332 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001333 }
1334
Wink Savillee68857d2014-10-17 15:23:05 -07001335 public boolean isStkDialogActivated(Context context) {
1336 String stkDialogActivity = "com.android.stk.StkDialogActivity";
1337 boolean activated = false;
1338 final ActivityManager am = (ActivityManager) context.getSystemService(
1339 Context.ACTIVITY_SERVICE);
1340 String topActivity = am.getRunningTasks(1).get(0).topActivity.getClassName();
1341
1342 CatLog.d(LOG_TAG, "isStkDialogActivated: " + topActivity);
1343 if (topActivity.equals(stkDialogActivity)) {
1344 activated = true;
1345 }
1346 CatLog.d(LOG_TAG, "activated : " + activated);
1347 return activated;
Johan Hellman3aec01c2011-02-10 10:15:28 +01001348 }
1349
Preeti Ahuja95919342013-10-01 18:18:55 -07001350 private void sendSetUpEventResponse(int event, byte[] addedInfo, int slotId) {
Preeti Ahuja414bc412013-06-25 19:31:49 -07001351 CatLog.d(this, "sendSetUpEventResponse: event : " + event + "slotId = " + slotId);
Preeti Ahuja95919342013-10-01 18:18:55 -07001352
1353 if (mStkContext[slotId].mCurrentSetupEventCmd == null){
1354 CatLog.e(this, "mCurrentSetupEventCmd is null");
1355 return;
1356 }
1357
1358 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentSetupEventCmd);
1359
1360 resMsg.setResultCode(ResultCode.OK);
1361 resMsg.setEventDownload(event, addedInfo);
1362
1363 mStkService[slotId].onCmdResponse(resMsg);
1364 }
1365
1366 private void checkForSetupEvent(int event, Bundle args, int slotId) {
1367 boolean eventPresent = false;
1368 byte[] addedInfo = null;
1369 CatLog.d(this, "Event :" + event);
1370
1371 if (mStkContext[slotId].mSetupEventListSettings != null) {
1372 /* Checks if the event is present in the EventList updated by last
1373 * SetupEventList Proactive Command */
1374 for (int i : mStkContext[slotId].mSetupEventListSettings.eventList) {
1375 if (event == i) {
1376 eventPresent = true;
1377 break;
1378 }
1379 }
1380
1381 /* If Event is present send the response to ICC */
1382 if (eventPresent == true) {
1383 CatLog.d(this, " Event " + event + "exists in the EventList");
1384
1385 switch (event) {
Preeti Ahuja560be362014-11-25 19:38:24 -08001386 case IDLE_SCREEN_AVAILABLE_EVENT:
1387 sendSetUpEventResponse(event, addedInfo, slotId);
1388 removeSetUpEvent(event, slotId);
1389 break;
Preeti Ahuja95919342013-10-01 18:18:55 -07001390 case LANGUAGE_SELECTION_EVENT:
1391 String language = mContext
1392 .getResources().getConfiguration().locale.getLanguage();
1393 CatLog.d(this, "language: " + language);
1394 // Each language code is a pair of alpha-numeric characters.
1395 // Each alpha-numeric character shall be coded on one byte
1396 // using the SMS default 7-bit coded alphabet
1397 addedInfo = GsmAlphabet.stringToGsm8BitPacked(language);
1398 sendSetUpEventResponse(event, addedInfo, slotId);
1399 break;
1400 default:
1401 break;
1402 }
1403 } else {
1404 CatLog.e(this, " Event does not exist in the EventList");
1405 }
1406 } else {
1407 CatLog.e(this, "SetupEventList is not received. Ignoring the event: " + event);
1408 }
1409 }
1410
1411 private void removeSetUpEvent(int event, int slotId) {
1412 CatLog.d(this, "Remove Event :" + event);
1413
1414 if (mStkContext[slotId].mSetupEventListSettings != null) {
1415 /*
1416 * Make new Eventlist without the event
1417 */
1418 for (int i = 0; i < mStkContext[slotId].mSetupEventListSettings.eventList.length; i++) {
1419 if (event == mStkContext[slotId].mSetupEventListSettings.eventList[i]) {
1420 mStkContext[slotId].mSetupEventListSettings.eventList[i] = INVALID_SETUP_EVENT;
1421 break;
1422 }
1423 }
1424 }
1425 }
1426
1427 private void launchEventMessage(int slotId) {
1428 launchEventMessage(slotId, mStkContext[slotId].mCurrentCmd.geTextMessage());
1429 }
1430
Wink Savillee68857d2014-10-17 15:23:05 -07001431 private void launchEventMessage(int slotId, TextMessage msg) {
1432 if (msg == null || (msg.text != null && msg.text.length() == 0)) {
1433 CatLog.d(LOG_TAG, "launchEventMessage return");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001434 return;
1435 }
Wink Savillee68857d2014-10-17 15:23:05 -07001436
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001437 Toast toast = new Toast(mContext.getApplicationContext());
1438 LayoutInflater inflate = (LayoutInflater) mContext
1439 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
1440 View v = inflate.inflate(R.layout.stk_event_msg, null);
1441 TextView tv = (TextView) v
1442 .findViewById(com.android.internal.R.id.message);
1443 ImageView iv = (ImageView) v
1444 .findViewById(com.android.internal.R.id.icon);
1445 if (msg.icon != null) {
1446 iv.setImageBitmap(msg.icon);
1447 } else {
1448 iv.setVisibility(View.GONE);
1449 }
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301450 /* In case of 'self explanatory' stkapp should display the specified
1451 * icon in proactive command (but not the alpha string).
1452 * If icon is non-self explanatory and if the icon could not be displayed
1453 * then alpha string or text data should be displayed
1454 * Ref: ETSI 102.223,section 6.5.4
1455 */
1456 if (mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ||
1457 msg.icon == null || !msg.iconSelfExplanatory) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001458 tv.setText(msg.text);
1459 }
1460
1461 toast.setView(v);
1462 toast.setDuration(Toast.LENGTH_LONG);
1463 toast.setGravity(Gravity.BOTTOM, 0, 0);
1464 toast.show();
1465 }
1466
Wink Savillee68857d2014-10-17 15:23:05 -07001467 private void launchConfirmationDialog(TextMessage msg, int slotId) {
1468 msg.title = mStkContext[slotId].lastSelectedItem;
1469 Intent newIntent = new Intent();
1470 String targetActivity = STK_DIALOG_ACTIVITY_NAME;
1471 String uriString = STK_DIALOG_URI + System.currentTimeMillis();
1472 //Set unique URI to create a new instance of activity for different slotId.
1473 Uri uriData = Uri.parse(uriString);
1474
1475 if (newIntent != null) {
1476 newIntent.setClassName(this, targetActivity);
1477 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1478 | Intent.FLAG_ACTIVITY_NO_HISTORY
1479 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
1480 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1481 newIntent.putExtra("TEXT", msg);
1482 newIntent.putExtra(SLOT_ID, slotId);
1483 newIntent.setData(uriData);
1484 startActivity(newIntent);
1485 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001486 }
1487
1488 private void launchBrowser(BrowserSettings settings) {
1489 if (settings == null) {
1490 return;
1491 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001492
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001493 Uri data = null;
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07001494 String url;
1495 if (settings.url == null) {
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001496 // if the command did not contain a URL,
1497 // launch the browser to the default homepage.
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07001498 CatLog.d(this, "no url data provided by proactive command." +
1499 " launching browser with stk default URL ... ");
1500 url = SystemProperties.get(STK_BROWSER_DEFAULT_URL_SYSPROP,
1501 "http://www.google.com");
1502 } else {
1503 CatLog.d(this, "launch browser command has attached url = " + settings.url);
1504 url = settings.url;
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001505 }
David Brown7c03cfe2011-10-20 15:36:12 -07001506
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07001507 if (url.startsWith("http://") || url.startsWith("https://")) {
1508 data = Uri.parse(url);
1509 CatLog.d(this, "launching browser with url = " + url);
1510 } else {
1511 String modifiedUrl = "http://" + url;
1512 data = Uri.parse(modifiedUrl);
1513 CatLog.d(this, "launching browser with modified url = " + modifiedUrl);
1514 }
1515
1516 Intent intent = new Intent(Intent.ACTION_VIEW);
1517 intent.setData(data);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001518 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1519 switch (settings.mode) {
1520 case USE_EXISTING_BROWSER:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001521 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1522 break;
1523 case LAUNCH_NEW_BROWSER:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001524 intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
1525 break;
1526 case LAUNCH_IF_NOT_ALREADY_LAUNCHED:
1527 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1528 break;
1529 }
1530 // start browser activity
1531 startActivity(intent);
1532 // a small delay, let the browser start, before processing the next command.
Wink Saville79085fc2009-06-09 10:27:23 -07001533 // this is good for scenarios where a related DISPLAY TEXT command is
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001534 // followed immediately.
1535 try {
Ryuto Sawada350aaa62016-06-13 14:47:22 +09001536 Thread.sleep(3000);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001537 } catch (InterruptedException e) {}
1538 }
1539
Wink Savillee68857d2014-10-17 15:23:05 -07001540 private void launchIdleText(int slotId) {
Preeti Ahuja560be362014-11-25 19:38:24 -08001541 TextMessage msg = mStkContext[slotId].mIdleModeTextCmd.geTextMessage();
dujin.cha2a0eb2a2011-11-11 15:03:57 +09001542
Preeti Ahuja95919342013-10-01 18:18:55 -07001543 if (msg == null || msg.text ==null) {
1544 CatLog.d(LOG_TAG, msg == null ? "mCurrent.getTextMessage is NULL"
1545 : "mCurrent.getTextMessage.text is NULL");
Wink Savillee68857d2014-10-17 15:23:05 -07001546 mNotificationManager.cancel(getNotificationId(slotId));
Wink Saville046db4b2011-11-01 20:42:54 -07001547 return;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001548 } else {
Preeti Ahuja95919342013-10-01 18:18:55 -07001549 CatLog.d(LOG_TAG, "launchIdleText - text[" + msg.text
1550 + "] iconSelfExplanatory[" + msg.iconSelfExplanatory
1551 + "] icon[" + msg.icon + "], sim id: " + slotId);
Wink Savillee68857d2014-10-17 15:23:05 -07001552 CatLog.d(LOG_TAG, "Add IdleMode text");
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001553 PendingIntent pendingIntent = PendingIntent.getService(mContext, 0,
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001554 new Intent(mContext, StkAppService.class), 0);
1555
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001556 final Notification.Builder notificationBuilder = new Notification.Builder(
1557 StkAppService.this);
Wink Savillee68857d2014-10-17 15:23:05 -07001558 if (mStkContext[slotId].mMainCmd != null &&
1559 mStkContext[slotId].mMainCmd.getMenu() != null) {
1560 notificationBuilder.setContentTitle(mStkContext[slotId].mMainCmd.getMenu().title);
Christopher Posselwhite2ad2ab72013-05-27 07:51:06 +02001561 } else {
1562 notificationBuilder.setContentTitle("");
1563 }
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001564 notificationBuilder
1565 .setSmallIcon(com.android.internal.R.drawable.stat_notify_sim_toolkit);
1566 notificationBuilder.setContentIntent(pendingIntent);
1567 notificationBuilder.setOngoing(true);
1568 // Set text and icon for the status bar and notification body.
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301569 if (mStkContext[slotId].mIdleModeTextCmd.hasIconLoadFailed() ||
1570 !msg.iconSelfExplanatory) {
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001571 notificationBuilder.setContentText(msg.text);
Christopher Posselwhite2ad2ab72013-05-27 07:51:06 +02001572 notificationBuilder.setTicker(msg.text);
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001573 }
1574 if (msg.icon != null) {
1575 notificationBuilder.setLargeIcon(msg.icon);
1576 } else {
1577 Bitmap bitmapIcon = BitmapFactory.decodeResource(StkAppService.this
1578 .getResources().getSystem(),
1579 com.android.internal.R.drawable.stat_notify_sim_toolkit);
1580 notificationBuilder.setLargeIcon(bitmapIcon);
1581 }
Selim Cinek62eb3fe2014-08-27 17:52:23 +02001582 notificationBuilder.setColor(mContext.getResources().getColor(
1583 com.android.internal.R.color.system_notification_accent_color));
Wink Savillee68857d2014-10-17 15:23:05 -07001584 mNotificationManager.notify(getNotificationId(slotId), notificationBuilder.build());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001585 }
1586 }
1587
Wink Savillee68857d2014-10-17 15:23:05 -07001588 private void launchToneDialog(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001589 Intent newIntent = new Intent(this, ToneDialog.class);
Wink Savillee68857d2014-10-17 15:23:05 -07001590 String uriString = STK_TONE_URI + slotId;
1591 Uri uriData = Uri.parse(uriString);
1592 //Set unique URI to create a new instance of activity for different slotId.
1593 CatLog.d(LOG_TAG, "launchToneDialog, slotId: " + slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001594 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1595 | Intent.FLAG_ACTIVITY_NO_HISTORY
1596 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
Wink Savillee68857d2014-10-17 15:23:05 -07001597 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1598 newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
1599 newIntent.putExtra("TONE", mStkContext[slotId].mCurrentCmd.getToneSettings());
1600 newIntent.putExtra(SLOT_ID, slotId);
1601 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001602 startActivity(newIntent);
1603 }
1604
Takanori Nakano49b12722016-02-16 14:34:14 +09001605 private void launchOpenChannelDialog(final int slotId) {
Wink Savillee68857d2014-10-17 15:23:05 -07001606 TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001607 if (msg == null) {
Wink Savillee68857d2014-10-17 15:23:05 -07001608 CatLog.d(LOG_TAG, "msg is null, return here");
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001609 return;
1610 }
1611
1612 msg.title = getResources().getString(R.string.stk_dialog_title);
1613 if (msg.text == null) {
1614 msg.text = getResources().getString(R.string.default_open_channel_msg);
1615 }
1616
1617 final AlertDialog dialog = new AlertDialog.Builder(mContext)
1618 .setIconAttribute(android.R.attr.alertDialogIcon)
1619 .setTitle(msg.title)
1620 .setMessage(msg.text)
1621 .setCancelable(false)
1622 .setPositiveButton(getResources().getString(R.string.stk_dialog_accept),
1623 new DialogInterface.OnClickListener() {
1624 public void onClick(DialogInterface dialog, int which) {
1625 Bundle args = new Bundle();
1626 args.putInt(RES_ID, RES_ID_CHOICE);
1627 args.putInt(CHOICE, YES);
1628 Message message = mServiceHandler.obtainMessage();
1629 message.arg1 = OP_RESPONSE;
Takanori Nakano49b12722016-02-16 14:34:14 +09001630 message.arg2 = slotId;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001631 message.obj = args;
1632 mServiceHandler.sendMessage(message);
1633 }
1634 })
1635 .setNegativeButton(getResources().getString(R.string.stk_dialog_reject),
1636 new DialogInterface.OnClickListener() {
1637 public void onClick(DialogInterface dialog, int which) {
1638 Bundle args = new Bundle();
1639 args.putInt(RES_ID, RES_ID_CHOICE);
1640 args.putInt(CHOICE, NO);
1641 Message message = mServiceHandler.obtainMessage();
1642 message.arg1 = OP_RESPONSE;
Takanori Nakano49b12722016-02-16 14:34:14 +09001643 message.arg2 = slotId;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001644 message.obj = args;
1645 mServiceHandler.sendMessage(message);
1646 }
1647 })
1648 .create();
1649
1650 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1651 if (!mContext.getResources().getBoolean(
1652 com.android.internal.R.bool.config_sf_slowBlur)) {
1653 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
1654 }
1655
1656 dialog.show();
1657 }
1658
Wink Savillee68857d2014-10-17 15:23:05 -07001659 private void launchTransientEventMessage(int slotId) {
1660 TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001661 if (msg == null) {
Wink Savillee68857d2014-10-17 15:23:05 -07001662 CatLog.d(LOG_TAG, "msg is null, return here");
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001663 return;
1664 }
1665
1666 msg.title = getResources().getString(R.string.stk_dialog_title);
1667
1668 final AlertDialog dialog = new AlertDialog.Builder(mContext)
1669 .setIconAttribute(android.R.attr.alertDialogIcon)
1670 .setTitle(msg.title)
1671 .setMessage(msg.text)
1672 .setCancelable(false)
1673 .setPositiveButton(getResources().getString(android.R.string.ok),
1674 new DialogInterface.OnClickListener() {
1675 public void onClick(DialogInterface dialog, int which) {
1676 }
1677 })
1678 .create();
1679
1680 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1681 if (!mContext.getResources().getBoolean(
1682 com.android.internal.R.bool.config_sf_slowBlur)) {
1683 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
1684 }
1685
1686 dialog.show();
1687 }
1688
Wink Savillee68857d2014-10-17 15:23:05 -07001689 private int getNotificationId(int slotId) {
1690 int notifyId = STK_NOTIFICATION_ID;
1691 if (slotId >= 0 && slotId < mSimCount) {
1692 notifyId += slotId;
1693 } else {
1694 CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
1695 }
1696 CatLog.d(LOG_TAG, "getNotificationId, slotId: " + slotId + ", notifyId: " + notifyId);
1697 return notifyId;
1698 }
1699
1700 private String getItemName(int itemId, int slotId) {
1701 Menu menu = mStkContext[slotId].mCurrentCmd.getMenu();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001702 if (menu == null) {
1703 return null;
1704 }
1705 for (Item item : menu.items) {
1706 if (item.id == itemId) {
1707 return item.text;
1708 }
1709 }
1710 return null;
1711 }
1712
Wink Savillee68857d2014-10-17 15:23:05 -07001713 private boolean removeMenu(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001714 try {
Wink Savillee68857d2014-10-17 15:23:05 -07001715 if (mStkContext[slotId].mCurrentMenu.items.size() == 1 &&
1716 mStkContext[slotId].mCurrentMenu.items.get(0) == null) {
1717 mStkContext[slotId].mSetupMenuState = STATE_NOT_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001718 return true;
1719 }
1720 } catch (NullPointerException e) {
Wink Savillee68857d2014-10-17 15:23:05 -07001721 CatLog.d(LOG_TAG, "Unable to get Menu's items size");
1722 mStkContext[slotId].mSetupMenuState = STATE_NOT_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001723 return true;
1724 }
Wink Savillee68857d2014-10-17 15:23:05 -07001725 mStkContext[slotId].mSetupMenuState = STATE_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001726 return false;
1727 }
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +05301728
Wink Savillee68857d2014-10-17 15:23:05 -07001729 StkContext getStkContext(int slotId) {
1730 if (slotId >= 0 && slotId < mSimCount) {
1731 return mStkContext[slotId];
1732 } else {
1733 CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
1734 return null;
1735 }
1736 }
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +05301737
1738 private void handleAlphaNotify(Bundle args) {
1739 String alphaString = args.getString(AppInterface.ALPHA_STRING);
1740
1741 CatLog.d(this, "Alpha string received from card: " + alphaString);
1742 Toast toast = Toast.makeText(sInstance, alphaString, Toast.LENGTH_LONG);
1743 toast.setGravity(Gravity.TOP, 0, 0);
1744 toast.show();
1745 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001746}