blob: c1f75e532419050dfab87592847377a6ceeb60bd [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;
Sooraj Sasindrana4160472016-10-12 16:28:25 -070043import android.os.PersistableBundle;
Preeti Ahuja560be362014-11-25 19:38:24 -080044import android.os.PowerManager;
Preeti Ahujaa7cdca22013-10-01 18:20:56 -070045import android.os.SystemProperties;
Preeti Ahuja95919342013-10-01 18:18:55 -070046import android.provider.Settings;
Sooraj Sasindrana4160472016-10-12 16:28:25 -070047import android.telephony.CarrierConfigManager;
Wink Saville56469d52009-04-02 01:37:03 -070048import android.telephony.TelephonyManager;
Preeti Ahujaa7cdca22013-10-01 18:20:56 -070049import android.text.TextUtils;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080050import android.view.Gravity;
51import android.view.LayoutInflater;
52import android.view.View;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -050053import android.view.Window;
54import android.view.WindowManager;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080055import android.widget.ImageView;
56import android.widget.RemoteViews;
57import android.widget.TextView;
58import android.widget.Toast;
Wink Savillee68857d2014-10-17 15:23:05 -070059import android.content.BroadcastReceiver;
60import android.content.IntentFilter;
61import android.content.pm.ApplicationInfo;
62import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080063
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070064import com.android.internal.telephony.cat.AppInterface;
Preeti Ahuja95919342013-10-01 18:18:55 -070065import com.android.internal.telephony.cat.LaunchBrowserMode;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070066import com.android.internal.telephony.cat.Menu;
67import com.android.internal.telephony.cat.Item;
Pierre Fröjd97503262010-11-08 13:59:36 +010068import com.android.internal.telephony.cat.Input;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070069import com.android.internal.telephony.cat.ResultCode;
70import com.android.internal.telephony.cat.CatCmdMessage;
71import com.android.internal.telephony.cat.CatCmdMessage.BrowserSettings;
Preeti Ahuja95919342013-10-01 18:18:55 -070072import com.android.internal.telephony.cat.CatCmdMessage.SetupEventListSettings;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070073import com.android.internal.telephony.cat.CatLog;
74import com.android.internal.telephony.cat.CatResponseMessage;
75import com.android.internal.telephony.cat.TextMessage;
Wink Saville94e982b2014-07-11 07:38:14 -070076import com.android.internal.telephony.uicc.IccRefreshResponse;
77import com.android.internal.telephony.uicc.IccCardStatus.CardState;
Wink Savillee68857d2014-10-17 15:23:05 -070078import com.android.internal.telephony.PhoneConstants;
79import com.android.internal.telephony.TelephonyIntents;
80import com.android.internal.telephony.IccCardConstants;
81import com.android.internal.telephony.uicc.UiccController;
Preeti Ahuja95919342013-10-01 18:18:55 -070082import com.android.internal.telephony.GsmAlphabet;
Legler Wuaeefef52014-10-27 00:57:18 +080083import com.android.internal.telephony.cat.CatService;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080084
Preeti Ahujaa7cdca22013-10-01 18:20:56 -070085import java.util.Iterator;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080086import java.util.LinkedList;
Wink Savillee68857d2014-10-17 15:23:05 -070087import java.lang.System;
88import java.util.List;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080089
Preeti Ahuja95919342013-10-01 18:18:55 -070090import static com.android.internal.telephony.cat.CatCmdMessage.
Preeti Ahuja560be362014-11-25 19:38:24 -080091 SetupEventListConstants.IDLE_SCREEN_AVAILABLE_EVENT;
92import static com.android.internal.telephony.cat.CatCmdMessage.
Preeti Ahuja95919342013-10-01 18:18:55 -070093 SetupEventListConstants.LANGUAGE_SELECTION_EVENT;
94
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080095/**
96 * SIM toolkit application level service. Interacts with Telephopny messages,
97 * application's launch and user input from STK UI elements.
Wink Saville79085fc2009-06-09 10:27:23 -070098 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080099 */
100public class StkAppService extends Service implements Runnable {
101
102 // members
Wink Savillee68857d2014-10-17 15:23:05 -0700103 protected class StkContext {
104 protected CatCmdMessage mMainCmd = null;
105 protected CatCmdMessage mCurrentCmd = null;
106 protected CatCmdMessage mCurrentMenuCmd = null;
107 protected Menu mCurrentMenu = null;
108 protected String lastSelectedItem = null;
109 protected boolean mMenuIsVisible = false;
110 protected boolean mIsInputPending = false;
111 protected boolean mIsMenuPending = false;
112 protected boolean mIsDialogPending = false;
113 protected boolean responseNeeded = true;
114 protected boolean launchBrowser = false;
115 protected BrowserSettings mBrowserSettings = null;
116 protected LinkedList<DelayedCmd> mCmdsQ = null;
117 protected boolean mCmdInProgress = false;
118 protected int mStkServiceState = STATE_UNKNOWN;
119 protected int mSetupMenuState = STATE_UNKNOWN;
120 protected int mMenuState = StkMenuActivity.STATE_INIT;
121 protected int mOpCode = -1;
122 private Activity mActivityInstance = null;
123 private Activity mDialogInstance = null;
124 private Activity mMainActivityInstance = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700125 private int mSlotId = 0;
Preeti Ahuja95919342013-10-01 18:18:55 -0700126 private SetupEventListSettings mSetupEventListSettings = null;
127 private boolean mClearSelectItem = false;
128 private boolean mDisplayTextDlgIsVisibile = false;
129 private CatCmdMessage mCurrentSetupEventCmd = null;
Preeti Ahuja560be362014-11-25 19:38:24 -0800130 private CatCmdMessage mIdleModeTextCmd = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700131 final synchronized void setPendingActivityInstance(Activity act) {
132 CatLog.d(this, "setPendingActivityInstance act : " + mSlotId + ", " + act);
133 callSetActivityInstMsg(OP_SET_ACT_INST, mSlotId, act);
134 }
135 final synchronized Activity getPendingActivityInstance() {
136 CatLog.d(this, "getPendingActivityInstance act : " + mSlotId + ", " +
137 mActivityInstance);
138 return mActivityInstance;
139 }
140 final synchronized void setPendingDialogInstance(Activity act) {
141 CatLog.d(this, "setPendingDialogInstance act : " + mSlotId + ", " + act);
142 callSetActivityInstMsg(OP_SET_DAL_INST, mSlotId, act);
143 }
144 final synchronized Activity getPendingDialogInstance() {
145 CatLog.d(this, "getPendingDialogInstance act : " + mSlotId + ", " +
146 mDialogInstance);
147 return mDialogInstance;
148 }
149 final synchronized void setMainActivityInstance(Activity act) {
150 CatLog.d(this, "setMainActivityInstance act : " + mSlotId + ", " + act);
151 callSetActivityInstMsg(OP_SET_MAINACT_INST, mSlotId, act);
152 }
153 final synchronized Activity getMainActivityInstance() {
154 CatLog.d(this, "getMainActivityInstance act : " + mSlotId + ", " +
155 mMainActivityInstance);
156 return mMainActivityInstance;
157 }
158 }
159
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800160 private volatile Looper mServiceLooper;
161 private volatile ServiceHandler mServiceHandler;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800162 private Context mContext = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800163 private NotificationManager mNotificationManager = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800164 static StkAppService sInstance = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700165 private AppInterface[] mStkService = null;
166 private StkContext[] mStkContext = null;
167 private int mSimCount = 0;
Preeti Ahuja560be362014-11-25 19:38:24 -0800168 private PowerManager mPowerManager = null;
169 private StkCmdReceiver mStkCmdReceiver = null;
Preeti Ahuja95919342013-10-01 18:18:55 -0700170
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800171 // Used for setting FLAG_ACTIVITY_NO_USER_ACTION when
172 // creating an intent.
173 private enum InitiatedByUserAction {
174 yes, // The action was started via a user initiated action
175 unknown, // Not known for sure if user initated the action
176 }
177
178 // constants
179 static final String OPCODE = "op";
180 static final String CMD_MSG = "cmd message";
181 static final String RES_ID = "response id";
182 static final String MENU_SELECTION = "menu selection";
183 static final String INPUT = "input";
184 static final String HELP = "help";
185 static final String CONFIRMATION = "confirm";
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500186 static final String CHOICE = "choice";
Wink Savillee68857d2014-10-17 15:23:05 -0700187 static final String SLOT_ID = "SLOT_ID";
188 static final String STK_CMD = "STK CMD";
189 static final String STK_DIALOG_URI = "stk://com.android.stk/dialog/";
190 static final String STK_MENU_URI = "stk://com.android.stk/menu/";
191 static final String STK_INPUT_URI = "stk://com.android.stk/input/";
192 static final String STK_TONE_URI = "stk://com.android.stk/tone/";
Preeti Ahuja95919342013-10-01 18:18:55 -0700193
194 // These below constants are used for SETUP_EVENT_LIST
195 static final String SETUP_EVENT_TYPE = "event";
196 static final String SETUP_EVENT_CAUSE = "cause";
197
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800198 // operations ids for different service functionality.
199 static final int OP_CMD = 1;
200 static final int OP_RESPONSE = 2;
201 static final int OP_LAUNCH_APP = 3;
202 static final int OP_END_SESSION = 4;
203 static final int OP_BOOT_COMPLETED = 5;
204 private static final int OP_DELAYED_MSG = 6;
Wink Saville94e982b2014-07-11 07:38:14 -0700205 static final int OP_CARD_STATUS_CHANGED = 7;
Wink Savillee68857d2014-10-17 15:23:05 -0700206 static final int OP_SET_ACT_INST = 8;
207 static final int OP_SET_DAL_INST = 9;
208 static final int OP_SET_MAINACT_INST = 10;
Preeti Ahujab3d0e612014-11-20 13:29:25 -0800209 static final int OP_LOCALE_CHANGED = 11;
210 static final int OP_ALPHA_NOTIFY = 12;
Preeti Ahuja560be362014-11-25 19:38:24 -0800211 static final int OP_IDLE_SCREEN = 13;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800212
Preeti Ahuja95919342013-10-01 18:18:55 -0700213 //Invalid SetupEvent
214 static final int INVALID_SETUP_EVENT = 0xFF;
215
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800216 // Response ids
217 static final int RES_ID_MENU_SELECTION = 11;
218 static final int RES_ID_INPUT = 12;
219 static final int RES_ID_CONFIRM = 13;
220 static final int RES_ID_DONE = 14;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500221 static final int RES_ID_CHOICE = 15;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800222
223 static final int RES_ID_TIMEOUT = 20;
224 static final int RES_ID_BACKWARD = 21;
225 static final int RES_ID_END_SESSION = 22;
226 static final int RES_ID_EXIT = 23;
227
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500228 static final int YES = 1;
229 static final int NO = 0;
230
Wink Savillee68857d2014-10-17 15:23:05 -0700231 static final int STATE_UNKNOWN = -1;
232 static final int STATE_NOT_EXIST = 0;
233 static final int STATE_EXIST = 1;
Wink Saville79085fc2009-06-09 10:27:23 -0700234
Wink Savillee68857d2014-10-17 15:23:05 -0700235 private static final String PACKAGE_NAME = "com.android.stk";
236 private static final String STK_MENU_ACTIVITY_NAME = PACKAGE_NAME + ".StkMenuActivity";
237 private static final String STK_INPUT_ACTIVITY_NAME = PACKAGE_NAME + ".StkInputActivity";
238 private static final String STK_DIALOG_ACTIVITY_NAME = PACKAGE_NAME + ".StkDialogActivity";
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800239 // Notification id used to display Idle Mode text in NotificationManager.
240 private static final int STK_NOTIFICATION_ID = 333;
Wink Savillee68857d2014-10-17 15:23:05 -0700241 private static final String LOG_TAG = new Object(){}.getClass().getEnclosingClass().getName();
Wink Saville79085fc2009-06-09 10:27:23 -0700242
243 // Inner class used for queuing telephony messages (proactive commands,
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800244 // session end) while the service is busy processing a previous message.
245 private class DelayedCmd {
246 // members
247 int id;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700248 CatCmdMessage msg;
Wink Savillee68857d2014-10-17 15:23:05 -0700249 int slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800250
Wink Savillee68857d2014-10-17 15:23:05 -0700251 DelayedCmd(int id, CatCmdMessage msg, int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800252 this.id = id;
253 this.msg = msg;
Wink Savillee68857d2014-10-17 15:23:05 -0700254 this.slotId = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800255 }
256 }
257
Preeti Ahujaa7cdca22013-10-01 18:20:56 -0700258 // system property to set the STK specific default url for launch browser proactive cmds
259 private static final String STK_BROWSER_DEFAULT_URL_SYSPROP = "persist.radio.stk.default_url";
260
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800261 @Override
262 public void onCreate() {
Wink Savillee68857d2014-10-17 15:23:05 -0700263 CatLog.d(LOG_TAG, "onCreate()+");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800264 // Initialize members
Wink Savillee68857d2014-10-17 15:23:05 -0700265 int i = 0;
266 mContext = getBaseContext();
267 mSimCount = TelephonyManager.from(mContext).getSimCount();
268 CatLog.d(LOG_TAG, "simCount: " + mSimCount);
269 mStkService = new AppInterface[mSimCount];
270 mStkContext = new StkContext[mSimCount];
Preeti Ahuja560be362014-11-25 19:38:24 -0800271 mPowerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
272 mStkCmdReceiver = new StkCmdReceiver();
273 registerReceiver(mStkCmdReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
Wink Savillee68857d2014-10-17 15:23:05 -0700274 for (i = 0; i < mSimCount; i++) {
275 CatLog.d(LOG_TAG, "slotId: " + i);
Legler Wuaeefef52014-10-27 00:57:18 +0800276 mStkService[i] = CatService.getInstance(i);
Wink Savillee68857d2014-10-17 15:23:05 -0700277 mStkContext[i] = new StkContext();
278 mStkContext[i].mSlotId = i;
279 mStkContext[i].mCmdsQ = new LinkedList<DelayedCmd>();
280 }
281
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800282 Thread serviceThread = new Thread(null, this, "Stk App Service");
283 serviceThread.start();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800284 mNotificationManager = (NotificationManager) mContext
285 .getSystemService(Context.NOTIFICATION_SERVICE);
286 sInstance = this;
287 }
288
289 @Override
290 public void onStart(Intent intent, int startId) {
Wink Savillee68857d2014-10-17 15:23:05 -0700291 if (intent == null) {
292 CatLog.d(LOG_TAG, "StkAppService onStart intent is null so return");
Banavathu, Srinivas Naik87cda962012-07-17 15:32:44 +0530293 return;
294 }
295
Wink Savillee68857d2014-10-17 15:23:05 -0700296 Bundle args = intent.getExtras();
297 if (args == null) {
298 CatLog.d(LOG_TAG, "StkAppService onStart args is null so return");
299 return;
300 }
301
302 int op = args.getInt(OPCODE);
303 int slotId = 0;
304 int i = 0;
305 if (op != OP_BOOT_COMPLETED) {
306 slotId = args.getInt(SLOT_ID);
307 }
Cuihtlauac ALVARADObde7f032015-05-29 16:25:12 +0200308 CatLog.d(LOG_TAG, "onStart sim id: " + slotId + ", op: " + op + ", *****");
Wink Savillee68857d2014-10-17 15:23:05 -0700309 if ((slotId >= 0 && slotId < mSimCount) && mStkService[slotId] == null) {
Legler Wuaeefef52014-10-27 00:57:18 +0800310 mStkService[slotId] = CatService.getInstance(slotId);
Wink Savillee68857d2014-10-17 15:23:05 -0700311 if (mStkService[slotId] == null) {
312 CatLog.d(LOG_TAG, "mStkService is: " + mStkContext[slotId].mStkServiceState);
313 mStkContext[slotId].mStkServiceState = STATE_NOT_EXIST;
314 //Check other StkService state.
315 //If all StkServices are not available, stop itself and uninstall apk.
316 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
317 if (i != slotId
Tsukasa Goto029332b2016-10-05 17:12:06 +0900318 && (mStkService[i] != null)
Wink Savillee68857d2014-10-17 15:23:05 -0700319 && (mStkContext[i].mStkServiceState == STATE_UNKNOWN
320 || mStkContext[i].mStkServiceState == STATE_EXIST)) {
321 break;
322 }
323 }
324 } else {
325 mStkContext[slotId].mStkServiceState = STATE_EXIST;
326 }
327 if (i == mSimCount) {
328 stopSelf();
329 StkAppInstaller.unInstall(mContext);
330 return;
331 }
332 }
333
Banavathu, Srinivas Naik87cda962012-07-17 15:32:44 +0530334 waitForLooper();
John Wang62acae42009-10-08 11:20:23 -0700335
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800336 Message msg = mServiceHandler.obtainMessage();
Wink Savillee68857d2014-10-17 15:23:05 -0700337 msg.arg1 = op;
338 msg.arg2 = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800339 switch(msg.arg1) {
340 case OP_CMD:
341 msg.obj = args.getParcelable(CMD_MSG);
342 break;
343 case OP_RESPONSE:
Wink Saville94e982b2014-07-11 07:38:14 -0700344 case OP_CARD_STATUS_CHANGED:
Preeti Ahuja95919342013-10-01 18:18:55 -0700345 case OP_LOCALE_CHANGED:
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +0530346 case OP_ALPHA_NOTIFY:
Preeti Ahuja560be362014-11-25 19:38:24 -0800347 case OP_IDLE_SCREEN:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800348 msg.obj = args;
349 /* falls through */
350 case OP_LAUNCH_APP:
351 case OP_END_SESSION:
352 case OP_BOOT_COMPLETED:
353 break;
354 default:
355 return;
356 }
357 mServiceHandler.sendMessage(msg);
358 }
359
360 @Override
361 public void onDestroy() {
Wink Savillee68857d2014-10-17 15:23:05 -0700362 CatLog.d(LOG_TAG, "onDestroy()");
Preeti Ahuja560be362014-11-25 19:38:24 -0800363 if (mStkCmdReceiver != null) {
364 unregisterReceiver(mStkCmdReceiver);
365 mStkCmdReceiver = null;
366 }
367 mPowerManager = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800368 waitForLooper();
369 mServiceLooper.quit();
370 }
371
372 @Override
373 public IBinder onBind(Intent intent) {
374 return null;
375 }
376
377 public void run() {
378 Looper.prepare();
379
380 mServiceLooper = Looper.myLooper();
381 mServiceHandler = new ServiceHandler();
382
383 Looper.loop();
384 }
385
386 /*
387 * Package api used by StkMenuActivity to indicate if its on the foreground.
388 */
Wink Savillee68857d2014-10-17 15:23:05 -0700389 void indicateMenuVisibility(boolean visibility, int slotId) {
390 if (slotId >= 0 && slotId < mSimCount) {
391 mStkContext[slotId].mMenuIsVisible = visibility;
392 }
393 }
394
Preeti Ahuja95919342013-10-01 18:18:55 -0700395 /*
396 * Package api used by StkDialogActivity to indicate if its on the foreground.
397 */
398 void setDisplayTextDlgVisibility(boolean visibility, int slotId) {
399 if (slotId >= 0 && slotId < mSimCount) {
400 mStkContext[slotId].mDisplayTextDlgIsVisibile = visibility;
401 }
402 }
403
Wink Savillee68857d2014-10-17 15:23:05 -0700404 boolean isInputPending(int slotId) {
405 if (slotId >= 0 && slotId < mSimCount) {
406 CatLog.d(LOG_TAG, "isInputFinishBySrv: " + mStkContext[slotId].mIsInputPending);
407 return mStkContext[slotId].mIsInputPending;
408 }
409 return false;
410 }
411
412 boolean isMenuPending(int slotId) {
413 if (slotId >= 0 && slotId < mSimCount) {
414 CatLog.d(LOG_TAG, "isMenuPending: " + mStkContext[slotId].mIsMenuPending);
415 return mStkContext[slotId].mIsMenuPending;
416 }
417 return false;
418 }
419
420 boolean isDialogPending(int slotId) {
421 if (slotId >= 0 && slotId < mSimCount) {
422 CatLog.d(LOG_TAG, "isDialogPending: " + mStkContext[slotId].mIsDialogPending);
423 return mStkContext[slotId].mIsDialogPending;
424 }
425 return false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800426 }
427
428 /*
429 * Package api used by StkMenuActivity to get its Menu parameter.
430 */
Wink Savillee68857d2014-10-17 15:23:05 -0700431 Menu getMenu(int slotId) {
432 CatLog.d(LOG_TAG, "StkAppService, getMenu, sim id: " + slotId);
433 if (slotId >=0 && slotId < mSimCount) {
434 return mStkContext[slotId].mCurrentMenu;
435 } else {
436 return null;
437 }
438 }
439
440 /*
441 * Package api used by StkMenuActivity to get its Main Menu parameter.
442 */
443 Menu getMainMenu(int slotId) {
444 CatLog.d(LOG_TAG, "StkAppService, getMainMenu, sim id: " + slotId);
w30234a08cffe2015-02-04 15:13:25 -0800445 if (slotId >=0 && slotId < mSimCount && (mStkContext[slotId].mMainCmd != null)) {
Wink Savillee68857d2014-10-17 15:23:05 -0700446 return mStkContext[slotId].mMainCmd.getMenu();
447 } else {
448 return null;
449 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800450 }
451
452 /*
453 * Package api used by UI Activities and Dialogs to communicate directly
454 * with the service to deliver state information and parameters.
455 */
456 static StkAppService getInstance() {
457 return sInstance;
458 }
459
460 private void waitForLooper() {
461 while (mServiceHandler == null) {
462 synchronized (this) {
463 try {
464 wait(100);
465 } catch (InterruptedException e) {
466 }
467 }
468 }
469 }
470
471 private final class ServiceHandler extends Handler {
472 @Override
473 public void handleMessage(Message msg) {
Wink Savillee68857d2014-10-17 15:23:05 -0700474 if(null == msg) {
475 CatLog.d(LOG_TAG, "ServiceHandler handleMessage msg is null");
476 return;
477 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800478 int opcode = msg.arg1;
Wink Savillee68857d2014-10-17 15:23:05 -0700479 int slotId = msg.arg2;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800480
Wink Savillee68857d2014-10-17 15:23:05 -0700481 CatLog.d(LOG_TAG, "handleMessage opcode[" + opcode + "], sim id[" + slotId + "]");
482 if (opcode == OP_CMD && msg.obj != null &&
483 ((CatCmdMessage)msg.obj).getCmdType()!= null) {
484 CatLog.d(LOG_TAG, "cmdName[" + ((CatCmdMessage)msg.obj).getCmdType().name() + "]");
485 }
486 mStkContext[slotId].mOpCode = opcode;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800487 switch (opcode) {
488 case OP_LAUNCH_APP:
Wink Savillee68857d2014-10-17 15:23:05 -0700489 if (mStkContext[slotId].mMainCmd == null) {
490 CatLog.d(LOG_TAG, "mMainCmd is null");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800491 // nothing todo when no SET UP MENU command didn't arrive.
492 return;
493 }
Wink Savillee68857d2014-10-17 15:23:05 -0700494 CatLog.d(LOG_TAG, "handleMessage OP_LAUNCH_APP - mCmdInProgress[" +
495 mStkContext[slotId].mCmdInProgress + "]");
496
497 //If there is a pending activity for the slot id,
498 //just finish it and create a new one to handle the pending command.
499 cleanUpInstanceStackBySlot(slotId);
500
Wink Savillee68857d2014-10-17 15:23:05 -0700501 CatLog.d(LOG_TAG, "Current cmd type: " +
502 mStkContext[slotId].mCurrentCmd.getCmdType());
503 //Restore the last command from stack by slot id.
504 restoreInstanceFromStackBySlot(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800505 break;
506 case OP_CMD:
Wink Savillee68857d2014-10-17 15:23:05 -0700507 CatLog.d(LOG_TAG, "[OP_CMD]");
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700508 CatCmdMessage cmdMsg = (CatCmdMessage) msg.obj;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800509 // There are two types of commands:
510 // 1. Interactive - user's response is required.
511 // 2. Informative - display a message, no interaction with the user.
512 //
Wink Saville79085fc2009-06-09 10:27:23 -0700513 // Informative commands can be handled immediately without any delay.
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800514 // Interactive commands can't override each other. So if a command
515 // is already in progress, we need to queue the next command until
516 // the user has responded or a timeout expired.
517 if (!isCmdInteractive(cmdMsg)) {
Wink Savillee68857d2014-10-17 15:23:05 -0700518 handleCmd(cmdMsg, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800519 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700520 if (!mStkContext[slotId].mCmdInProgress) {
521 mStkContext[slotId].mCmdInProgress = true;
522 handleCmd((CatCmdMessage) msg.obj, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800523 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700524 CatLog.d(LOG_TAG, "[Interactive][in progress]");
525 mStkContext[slotId].mCmdsQ.addLast(new DelayedCmd(OP_CMD,
526 (CatCmdMessage) msg.obj, slotId));
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800527 }
528 }
529 break;
530 case OP_RESPONSE:
Preeti Ahuja414bc412013-06-25 19:31:49 -0700531 handleCmdResponse((Bundle) msg.obj, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800532 // call delayed commands if needed.
Wink Savillee68857d2014-10-17 15:23:05 -0700533 if (mStkContext[slotId].mCmdsQ.size() != 0) {
534 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800535 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700536 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800537 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800538 break;
539 case OP_END_SESSION:
Wink Savillee68857d2014-10-17 15:23:05 -0700540 if (!mStkContext[slotId].mCmdInProgress) {
541 mStkContext[slotId].mCmdInProgress = true;
542 handleSessionEnd(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800543 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700544 mStkContext[slotId].mCmdsQ.addLast(
545 new DelayedCmd(OP_END_SESSION, null, slotId));
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800546 }
547 break;
548 case OP_BOOT_COMPLETED:
Wink Savillee68857d2014-10-17 15:23:05 -0700549 CatLog.d(LOG_TAG, " OP_BOOT_COMPLETED");
550 int i = 0;
551 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
552 if (mStkContext[i].mMainCmd != null) {
553 break;
554 }
555 }
556 if (i == mSimCount) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800557 StkAppInstaller.unInstall(mContext);
558 }
559 break;
560 case OP_DELAYED_MSG:
Wink Savillee68857d2014-10-17 15:23:05 -0700561 handleDelayedCmd(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800562 break;
Wink Saville94e982b2014-07-11 07:38:14 -0700563 case OP_CARD_STATUS_CHANGED:
Wink Savillee68857d2014-10-17 15:23:05 -0700564 CatLog.d(LOG_TAG, "Card/Icc Status change received");
565 handleCardStatusChangeAndIccRefresh((Bundle) msg.obj, slotId);
566 break;
567 case OP_SET_ACT_INST:
568 Activity act = new Activity();
569 act = (Activity) msg.obj;
570 CatLog.d(LOG_TAG, "Set activity instance. " + act);
571 mStkContext[slotId].mActivityInstance = act;
572 break;
573 case OP_SET_DAL_INST:
574 Activity dal = new Activity();
575 CatLog.d(LOG_TAG, "Set dialog instance. " + dal);
576 dal = (Activity) msg.obj;
577 mStkContext[slotId].mDialogInstance = dal;
578 break;
579 case OP_SET_MAINACT_INST:
580 Activity mainAct = new Activity();
581 mainAct = (Activity) msg.obj;
582 CatLog.d(LOG_TAG, "Set activity instance. " + mainAct);
583 mStkContext[slotId].mMainActivityInstance = mainAct;
Wink Saville94e982b2014-07-11 07:38:14 -0700584 break;
Preeti Ahuja95919342013-10-01 18:18:55 -0700585 case OP_LOCALE_CHANGED:
586 CatLog.d(this, "Locale Changed");
Yuta Ui1481b172016-02-03 15:34:31 +0900587 for (int slot = PhoneConstants.SIM_ID_1; slot < mSimCount; slot++) {
588 checkForSetupEvent(LANGUAGE_SELECTION_EVENT, (Bundle) msg.obj, slot);
589 }
Preeti Ahuja95919342013-10-01 18:18:55 -0700590 break;
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +0530591 case OP_ALPHA_NOTIFY:
592 handleAlphaNotify((Bundle) msg.obj);
593 break;
Preeti Ahuja560be362014-11-25 19:38:24 -0800594 case OP_IDLE_SCREEN:
595 for (int slot = 0; slot < mSimCount; slot++) {
596 if (mStkContext[slot] != null) {
597 handleIdleScreen(slot);
598 }
599 }
600 break;
Wink Saville94e982b2014-07-11 07:38:14 -0700601 }
602 }
603
Wink Savillee68857d2014-10-17 15:23:05 -0700604 private void handleCardStatusChangeAndIccRefresh(Bundle args, int slotId) {
Wink Saville94e982b2014-07-11 07:38:14 -0700605 boolean cardStatus = args.getBoolean(AppInterface.CARD_STATUS);
606
Wink Savillee68857d2014-10-17 15:23:05 -0700607 CatLog.d(LOG_TAG, "CardStatus: " + cardStatus);
Wink Saville94e982b2014-07-11 07:38:14 -0700608 if (cardStatus == false) {
Wink Savillee68857d2014-10-17 15:23:05 -0700609 CatLog.d(LOG_TAG, "CARD is ABSENT");
Wink Saville94e982b2014-07-11 07:38:14 -0700610 // Uninstall STKAPP, Clear Idle text, Stop StkAppService
Wink Savillee68857d2014-10-17 15:23:05 -0700611 mNotificationManager.cancel(getNotificationId(slotId));
612 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
Sooraj Sasindrana4160472016-10-12 16:28:25 -0700817 /**
818 * Get the boolean config from carrier config manager.
819 *
820 * @param context the context to get carrier service
821 * @param key config key defined in CarrierConfigManager
822 * @return boolean value of corresponding key.
823 */
824 private static boolean getBooleanCarrierConfig(Context context, String key) {
825 CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(
826 Context.CARRIER_CONFIG_SERVICE);
827 PersistableBundle b = null;
828 if (configManager != null) {
829 b = configManager.getConfig();
830 }
831 if (b != null) {
832 return b.getBoolean(key);
833 } else {
834 // Return static default defined in CarrierConfigManager.
835 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
836 }
837 }
838
Wink Savillee68857d2014-10-17 15:23:05 -0700839 private void handleCmd(CatCmdMessage cmdMsg, int slotId) {
Preeti Ahuja95919342013-10-01 18:18:55 -0700840
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800841 if (cmdMsg == null) {
842 return;
843 }
844 // save local reference for state tracking.
Wink Savillee68857d2014-10-17 15:23:05 -0700845 mStkContext[slotId].mCurrentCmd = cmdMsg;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800846 boolean waitForUsersResponse = true;
847
Wink Savillee68857d2014-10-17 15:23:05 -0700848 mStkContext[slotId].mIsInputPending = false;
849 mStkContext[slotId].mIsMenuPending = false;
850 mStkContext[slotId].mIsDialogPending = false;
851
852 CatLog.d(LOG_TAG,"[handleCmd]" + cmdMsg.getCmdType().name());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800853 switch (cmdMsg.getCmdType()) {
854 case DISPLAY_TEXT:
855 TextMessage msg = cmdMsg.geTextMessage();
Jeevaka Badrappan854a25c2012-12-01 16:32:03 +0200856 waitForUsersResponse = msg.responseNeeded;
Wink Savillee68857d2014-10-17 15:23:05 -0700857 if (mStkContext[slotId].lastSelectedItem != null) {
858 msg.title = mStkContext[slotId].lastSelectedItem;
859 } else if (mStkContext[slotId].mMainCmd != null){
860 msg.title = mStkContext[slotId].mMainCmd.getMenu().title;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800861 } else {
862 // TODO: get the carrier name from the SIM
863 msg.title = "";
864 }
Preeti Ahuja560be362014-11-25 19:38:24 -0800865 //If we receive a low priority Display Text and the device is
866 // not displaying any STK related activity and the screen is not idle
867 // ( that is, device is in an interactive state), then send a screen busy
868 // terminal response. Otherwise display the message. The existing
869 // displayed message shall be updated with the new display text
870 // proactive command (Refer to ETSI TS 102 384 section 27.22.4.1.4.4.2).
871 if (!(msg.isHighPriority || mStkContext[slotId].mMenuIsVisible
872 || mStkContext[slotId].mDisplayTextDlgIsVisibile || isTopOfStack())) {
873 if(!isScreenIdle()) {
874 CatLog.d(LOG_TAG, "Screen is not idle");
875 sendScreenBusyResponse(slotId);
876 } else {
877 launchTextDialog(slotId);
878 }
879 } else {
880 launchTextDialog(slotId);
881 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800882 break;
883 case SELECT_ITEM:
Wink Savillee68857d2014-10-17 15:23:05 -0700884 CatLog.d(LOG_TAG, "SELECT_ITEM +");
885 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
886 mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
887 launchMenuActivity(cmdMsg.getMenu(), slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800888 break;
889 case SET_UP_MENU:
Wink Savillee68857d2014-10-17 15:23:05 -0700890 mStkContext[slotId].mCmdInProgress = false;
891 mStkContext[slotId].mMainCmd = mStkContext[slotId].mCurrentCmd;
892 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
893 mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
894 CatLog.d(LOG_TAG, "SET_UP_MENU [" + removeMenu(slotId) + "]");
895
896 if (removeMenu(slotId)) {
897 int i = 0;
898 CatLog.d(LOG_TAG, "removeMenu() - Uninstall App");
899 mStkContext[slotId].mCurrentMenu = null;
Preeti Ahuja95919342013-10-01 18:18:55 -0700900 mStkContext[slotId].mMainCmd = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700901 //Check other setup menu state. If all setup menu are removed, uninstall apk.
902 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
903 if (i != slotId
Ryuto Sawadaf51e5e02016-11-25 17:12:49 +0900904 && (mStkContext[i].mSetupMenuState == STATE_UNKNOWN
905 || mStkContext[i].mSetupMenuState == STATE_EXIST)) {
Wink Savillee68857d2014-10-17 15:23:05 -0700906 CatLog.d(LOG_TAG, "Not Uninstall App:" + i + ","
Ryuto Sawadaf51e5e02016-11-25 17:12:49 +0900907 + mStkContext[i].mSetupMenuState);
Wink Savillee68857d2014-10-17 15:23:05 -0700908 break;
909 }
910 }
911 if (i == mSimCount) {
912 StkAppInstaller.unInstall(mContext);
913 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800914 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700915 CatLog.d(LOG_TAG, "install App");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800916 StkAppInstaller.install(mContext);
917 }
Wink Savillee68857d2014-10-17 15:23:05 -0700918 if (mStkContext[slotId].mMenuIsVisible) {
919 launchMenuActivity(null, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800920 }
921 break;
922 case GET_INPUT:
923 case GET_INKEY:
Wink Savillee68857d2014-10-17 15:23:05 -0700924 launchInputActivity(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800925 break;
926 case SET_UP_IDLE_MODE_TEXT:
927 waitForUsersResponse = false;
Preeti Ahuja560be362014-11-25 19:38:24 -0800928 mStkContext[slotId].mIdleModeTextCmd = mStkContext[slotId].mCurrentCmd;
929 TextMessage idleModeText = mStkContext[slotId].mCurrentCmd.geTextMessage();
930 if (idleModeText == null) {
931 launchIdleText(slotId);
932 mStkContext[slotId].mIdleModeTextCmd = null;
933 }
934 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
935 if ((mStkContext[slotId].mIdleModeTextCmd != null) && isScreenIdle()) {
936 CatLog.d(this, "set up idle mode");
937 launchIdleText(slotId);
938 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800939 break;
940 case SEND_DTMF:
941 case SEND_SMS:
942 case SEND_SS:
943 case SEND_USSD:
Preeti Ahuja95919342013-10-01 18:18:55 -0700944 case GET_CHANNEL_STATUS:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800945 waitForUsersResponse = false;
Wink Savillee68857d2014-10-17 15:23:05 -0700946 launchEventMessage(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800947 break;
948 case LAUNCH_BROWSER:
Ryuto Sawada0bdc7192016-04-18 12:10:56 +0900949 // The device setup process should not be interrupted by launching browser.
950 if (Settings.Global.getInt(mContext.getContentResolver(),
951 Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
952 CatLog.d(this, "The command is not performed if the setup has not been completed.");
953 sendScreenBusyResponse(slotId);
954 break;
955 }
Sooraj Sasindrana4160472016-10-12 16:28:25 -0700956
957 /* Check if Carrier would not want to launch browser */
958 if (getBooleanCarrierConfig(mContext,
959 CarrierConfigManager.KEY_STK_DISABLE_LAUNCH_BROWSER_BOOL)) {
960 CatLog.d(this, "Browser is not launched as per carrier.");
961 sendResponse(RES_ID_DONE, slotId, true);
962 break;
963 }
964
Preeti Ahujaa7cdca22013-10-01 18:20:56 -0700965 TextMessage alphaId = mStkContext[slotId].mCurrentCmd.geTextMessage();
966 if ((mStkContext[slotId].mCurrentCmd.getBrowserSettings().mode
967 == LaunchBrowserMode.LAUNCH_IF_NOT_ALREADY_LAUNCHED) &&
968 ((alphaId == null) || TextUtils.isEmpty(alphaId.text))) {
969 // don't need user confirmation in this case
970 // just launch the browser or spawn a new tab
971 CatLog.d(this, "Browser mode is: launch if not already launched " +
972 "and user confirmation is not currently needed.\n" +
973 "supressing confirmation dialogue and confirming silently...");
974 mStkContext[slotId].launchBrowser = true;
975 mStkContext[slotId].mBrowserSettings =
976 mStkContext[slotId].mCurrentCmd.getBrowserSettings();
977 sendResponse(RES_ID_CONFIRM, slotId, true);
978 } else {
979 launchConfirmationDialog(alphaId, slotId);
980 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800981 break;
982 case SET_UP_CALL:
Preeti Ahujadd240102013-08-30 17:25:06 -0700983 TextMessage mesg = mStkContext[slotId].mCurrentCmd.getCallSettings().confirmMsg;
984 if((mesg != null) && (mesg.text == null || mesg.text.length() == 0)) {
985 mesg.text = getResources().getString(R.string.default_setup_call_msg);
986 }
987 CatLog.d(this, "SET_UP_CALL mesg.text " + mesg.text);
988 launchConfirmationDialog(mesg, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800989 break;
990 case PLAY_TONE:
Wink Savillee68857d2014-10-17 15:23:05 -0700991 launchToneDialog(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800992 break;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500993 case OPEN_CHANNEL:
Wink Savillee68857d2014-10-17 15:23:05 -0700994 launchOpenChannelDialog(slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500995 break;
996 case CLOSE_CHANNEL:
997 case RECEIVE_DATA:
998 case SEND_DATA:
Wink Savillee68857d2014-10-17 15:23:05 -0700999 TextMessage m = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001000
1001 if ((m != null) && (m.text == null)) {
1002 switch(cmdMsg.getCmdType()) {
1003 case CLOSE_CHANNEL:
1004 m.text = getResources().getString(R.string.default_close_channel_msg);
1005 break;
1006 case RECEIVE_DATA:
1007 m.text = getResources().getString(R.string.default_receive_data_msg);
1008 break;
1009 case SEND_DATA:
1010 m.text = getResources().getString(R.string.default_send_data_msg);
1011 break;
1012 }
1013 }
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001014 /*
1015 * Display indication in the form of a toast to the user if required.
1016 */
Wink Savillee68857d2014-10-17 15:23:05 -07001017 launchEventMessage(slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001018 break;
Preeti Ahuja95919342013-10-01 18:18:55 -07001019 case SET_UP_EVENT_LIST:
1020 mStkContext[slotId].mSetupEventListSettings =
1021 mStkContext[slotId].mCurrentCmd.getSetEventList();
1022 mStkContext[slotId].mCurrentSetupEventCmd = mStkContext[slotId].mCurrentCmd;
1023 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
Preeti Ahuja560be362014-11-25 19:38:24 -08001024 if (isScreenIdle()) {
1025 CatLog.d(this," Check if IDLE_SCREEN_AVAILABLE_EVENT is present in List");
1026 checkForSetupEvent(IDLE_SCREEN_AVAILABLE_EVENT, null, slotId);
1027 }
Preeti Ahuja95919342013-10-01 18:18:55 -07001028 break;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001029 }
1030
1031 if (!waitForUsersResponse) {
Wink Savillee68857d2014-10-17 15:23:05 -07001032 if (mStkContext[slotId].mCmdsQ.size() != 0) {
1033 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001034 } else {
Wink Savillee68857d2014-10-17 15:23:05 -07001035 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001036 }
1037 }
1038 }
1039
Wink Savillee68857d2014-10-17 15:23:05 -07001040 private void handleCmdResponse(Bundle args, int slotId) {
1041 CatLog.d(LOG_TAG, "handleCmdResponse, sim id: " + slotId);
1042 if (mStkContext[slotId].mCurrentCmd == null) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001043 return;
1044 }
Wink Savillee68857d2014-10-17 15:23:05 -07001045
1046 if (mStkService[slotId] == null) {
Legler Wuaeefef52014-10-27 00:57:18 +08001047 mStkService[slotId] = CatService.getInstance(slotId);
Wink Savillee68857d2014-10-17 15:23:05 -07001048 if (mStkService[slotId] == null) {
Alex Yakavenkad8e2ecd2012-04-20 17:10:15 -07001049 // This should never happen (we should be responding only to a message
1050 // that arrived from StkService). It has to exist by this time
Wink Savillee68857d2014-10-17 15:23:05 -07001051 CatLog.d(LOG_TAG, "Exception! mStkService is null when we need to send response.");
Alex Yakavenkad8e2ecd2012-04-20 17:10:15 -07001052 throw new RuntimeException("mStkService is null when we need to send response");
1053 }
1054 }
1055
Wink Savillee68857d2014-10-17 15:23:05 -07001056 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentCmd);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001057
1058 // set result code
1059 boolean helpRequired = args.getBoolean(HELP, false);
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001060 boolean confirmed = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001061
1062 switch(args.getInt(RES_ID)) {
1063 case RES_ID_MENU_SELECTION:
Wink Savillee68857d2014-10-17 15:23:05 -07001064 CatLog.d(LOG_TAG, "MENU_SELECTION=" + mStkContext[slotId].
1065 mCurrentMenuCmd.getCmdType());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001066 int menuSelection = args.getInt(MENU_SELECTION);
Wink Savillee68857d2014-10-17 15:23:05 -07001067 switch(mStkContext[slotId].mCurrentMenuCmd.getCmdType()) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001068 case SET_UP_MENU:
1069 case SELECT_ITEM:
Wink Savillee68857d2014-10-17 15:23:05 -07001070 mStkContext[slotId].lastSelectedItem = getItemName(menuSelection, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001071 if (helpRequired) {
1072 resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
1073 } else {
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301074 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1075 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001076 }
1077 resMsg.setMenuSelection(menuSelection);
1078 break;
1079 }
1080 break;
1081 case RES_ID_INPUT:
Wink Savillee68857d2014-10-17 15:23:05 -07001082 CatLog.d(LOG_TAG, "RES_ID_INPUT");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001083 String input = args.getString(INPUT);
Wink Savillee68857d2014-10-17 15:23:05 -07001084 if (input != null && (null != mStkContext[slotId].mCurrentCmd.geInput()) &&
1085 (mStkContext[slotId].mCurrentCmd.geInput().yesNo)) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001086 boolean yesNoSelection = input
1087 .equals(StkInputActivity.YES_STR_RESPONSE);
1088 resMsg.setYesNo(yesNoSelection);
1089 } else {
1090 if (helpRequired) {
1091 resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
1092 } else {
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301093 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1094 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001095 resMsg.setInput(input);
1096 }
1097 }
1098 break;
1099 case RES_ID_CONFIRM:
Alex Yakavenkad41f1d92010-07-12 14:13:13 -07001100 CatLog.d(this, "RES_ID_CONFIRM");
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001101 confirmed = args.getBoolean(CONFIRMATION);
Wink Savillee68857d2014-10-17 15:23:05 -07001102 switch (mStkContext[slotId].mCurrentCmd.getCmdType()) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001103 case DISPLAY_TEXT:
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301104 if (confirmed) {
1105 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1106 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
1107 } else {
1108 resMsg.setResultCode(ResultCode.UICC_SESSION_TERM_BY_USER);
1109 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001110 break;
1111 case LAUNCH_BROWSER:
1112 resMsg.setResultCode(confirmed ? ResultCode.OK
1113 : ResultCode.UICC_SESSION_TERM_BY_USER);
1114 if (confirmed) {
Wink Savillee68857d2014-10-17 15:23:05 -07001115 mStkContext[slotId].launchBrowser = true;
1116 mStkContext[slotId].mBrowserSettings =
1117 mStkContext[slotId].mCurrentCmd.getBrowserSettings();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001118 }
1119 break;
1120 case SET_UP_CALL:
1121 resMsg.setResultCode(ResultCode.OK);
1122 resMsg.setConfirmation(confirmed);
1123 if (confirmed) {
Wink Savillee68857d2014-10-17 15:23:05 -07001124 launchEventMessage(slotId,
1125 mStkContext[slotId].mCurrentCmd.getCallSettings().callMsg);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001126 }
1127 break;
1128 }
1129 break;
1130 case RES_ID_DONE:
1131 resMsg.setResultCode(ResultCode.OK);
1132 break;
1133 case RES_ID_BACKWARD:
Wink Savillee68857d2014-10-17 15:23:05 -07001134 CatLog.d(LOG_TAG, "RES_ID_BACKWARD");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001135 resMsg.setResultCode(ResultCode.BACKWARD_MOVE_BY_USER);
1136 break;
1137 case RES_ID_END_SESSION:
Wink Savillee68857d2014-10-17 15:23:05 -07001138 CatLog.d(LOG_TAG, "RES_ID_END_SESSION");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001139 resMsg.setResultCode(ResultCode.UICC_SESSION_TERM_BY_USER);
1140 break;
1141 case RES_ID_TIMEOUT:
Wink Savillee68857d2014-10-17 15:23:05 -07001142 CatLog.d(LOG_TAG, "RES_ID_TIMEOUT");
Naveen Kallad5176892009-11-30 12:45:29 -08001143 // GCF test-case 27.22.4.1.1 Expected Sequence 1.5 (DISPLAY TEXT,
1144 // Clear message after delay, successful) expects result code OK.
1145 // If the command qualifier specifies no user response is required
1146 // then send OK instead of NO_RESPONSE_FROM_USER
Wink Savillee68857d2014-10-17 15:23:05 -07001147 if ((mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1148 AppInterface.CommandType.DISPLAY_TEXT.value())
1149 && (mStkContext[slotId].mCurrentCmd.geTextMessage().userClear == false)) {
Naveen Kallad5176892009-11-30 12:45:29 -08001150 resMsg.setResultCode(ResultCode.OK);
1151 } else {
1152 resMsg.setResultCode(ResultCode.NO_RESPONSE_FROM_USER);
1153 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001154 break;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001155 case RES_ID_CHOICE:
1156 int choice = args.getInt(CHOICE);
1157 CatLog.d(this, "User Choice=" + choice);
1158 switch (choice) {
1159 case YES:
1160 resMsg.setResultCode(ResultCode.OK);
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001161 confirmed = true;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001162 break;
1163 case NO:
1164 resMsg.setResultCode(ResultCode.USER_NOT_ACCEPT);
1165 break;
1166 }
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001167
Wink Savillee68857d2014-10-17 15:23:05 -07001168 if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1169 AppInterface.CommandType.OPEN_CHANNEL.value()) {
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001170 resMsg.setConfirmation(confirmed);
1171 }
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001172 break;
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001173
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001174 default:
Wink Savillee68857d2014-10-17 15:23:05 -07001175 CatLog.d(LOG_TAG, "Unknown result id");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001176 return;
1177 }
Wink Savillee68857d2014-10-17 15:23:05 -07001178
1179 if (null != mStkContext[slotId].mCurrentCmd &&
1180 null != mStkContext[slotId].mCurrentCmd.getCmdType()) {
1181 CatLog.d(LOG_TAG, "handleCmdResponse- cmdName[" +
1182 mStkContext[slotId].mCurrentCmd.getCmdType().name() + "]");
1183 }
1184 mStkService[slotId].onCmdResponse(resMsg);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001185 }
1186
1187 /**
1188 * Returns 0 or FLAG_ACTIVITY_NO_USER_ACTION, 0 means the user initiated the action.
1189 *
1190 * @param userAction If the userAction is yes then we always return 0 otherwise
1191 * mMenuIsVisible is used to determine what to return. If mMenuIsVisible is true
1192 * then we are the foreground app and we'll return 0 as from our perspective a
1193 * user action did cause. If it's false than we aren't the foreground app and
1194 * FLAG_ACTIVITY_NO_USER_ACTION is returned.
Wink Saville79085fc2009-06-09 10:27:23 -07001195 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001196 * @return 0 or FLAG_ACTIVITY_NO_USER_ACTION
1197 */
Wink Savillee68857d2014-10-17 15:23:05 -07001198 private int getFlagActivityNoUserAction(InitiatedByUserAction userAction, int slotId) {
1199 return ((userAction == InitiatedByUserAction.yes) | mStkContext[slotId].mMenuIsVisible)
1200 ? 0 : Intent.FLAG_ACTIVITY_NO_USER_ACTION;
1201 }
1202 /**
1203 * This method is used for cleaning up pending instances in stack.
1204 */
1205 private void cleanUpInstanceStackBySlot(int slotId) {
1206 Activity activity = mStkContext[slotId].getPendingActivityInstance();
1207 Activity dialog = mStkContext[slotId].getPendingDialogInstance();
1208 CatLog.d(LOG_TAG, "cleanUpInstanceStackBySlot slotId: " + slotId);
Legler Wuaeefef52014-10-27 00:57:18 +08001209 if (mStkContext[slotId].mCurrentCmd == null) {
1210 CatLog.d(LOG_TAG, "current cmd is null.");
1211 return;
1212 }
Wink Savillee68857d2014-10-17 15:23:05 -07001213 if (activity != null) {
1214 CatLog.d(LOG_TAG, "current cmd type: " +
1215 mStkContext[slotId].mCurrentCmd.getCmdType());
1216 if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1217 AppInterface.CommandType.GET_INPUT.value() ||
1218 mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1219 AppInterface.CommandType.GET_INKEY.value()) {
1220 mStkContext[slotId].mIsInputPending = true;
1221 } else if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1222 AppInterface.CommandType.SET_UP_MENU.value() ||
1223 mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1224 AppInterface.CommandType.SELECT_ITEM.value()) {
1225 mStkContext[slotId].mIsMenuPending = true;
1226 } else {
1227 }
1228 CatLog.d(LOG_TAG, "finish pending activity.");
1229 activity.finish();
1230 mStkContext[slotId].mActivityInstance = null;
1231 }
1232 if (dialog != null) {
1233 CatLog.d(LOG_TAG, "finish pending dialog.");
1234 mStkContext[slotId].mIsDialogPending = true;
1235 dialog.finish();
1236 mStkContext[slotId].mDialogInstance = null;
1237 }
1238 }
1239 /**
1240 * This method is used for restoring pending instances from stack.
1241 */
1242 private void restoreInstanceFromStackBySlot(int slotId) {
1243 AppInterface.CommandType cmdType = mStkContext[slotId].mCurrentCmd.getCmdType();
1244
1245 CatLog.d(LOG_TAG, "restoreInstanceFromStackBySlot cmdType : " + cmdType);
1246 switch(cmdType) {
1247 case GET_INPUT:
1248 case GET_INKEY:
1249 launchInputActivity(slotId);
1250 //Set mMenuIsVisible to true for showing main menu for
1251 //following session end command.
1252 mStkContext[slotId].mMenuIsVisible = true;
1253 break;
1254 case DISPLAY_TEXT:
1255 launchTextDialog(slotId);
1256 break;
1257 case LAUNCH_BROWSER:
1258 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.geTextMessage(),
1259 slotId);
1260 break;
1261 case OPEN_CHANNEL:
1262 launchOpenChannelDialog(slotId);
1263 break;
1264 case SET_UP_CALL:
1265 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.getCallSettings().
1266 confirmMsg, slotId);
1267 break;
1268 case SET_UP_MENU:
1269 case SELECT_ITEM:
1270 launchMenuActivity(null, slotId);
1271 break;
1272 default:
1273 break;
1274 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001275 }
1276
Wink Savillee68857d2014-10-17 15:23:05 -07001277 private void launchMenuActivity(Menu menu, int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001278 Intent newIntent = new Intent(Intent.ACTION_VIEW);
Wink Savillee68857d2014-10-17 15:23:05 -07001279 String targetActivity = STK_MENU_ACTIVITY_NAME;
1280 String uriString = STK_MENU_URI + System.currentTimeMillis();
1281 //Set unique URI to create a new instance of activity for different slotId.
1282 Uri uriData = Uri.parse(uriString);
1283
1284 CatLog.d(LOG_TAG, "launchMenuActivity, slotId: " + slotId + " , " +
1285 uriData.toString() + " , " + mStkContext[slotId].mOpCode + ", "
1286 + mStkContext[slotId].mMenuState);
1287 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1288 int intentFlags = Intent.FLAG_ACTIVITY_NEW_TASK;
1289
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001290 if (menu == null) {
1291 // We assume this was initiated by the user pressing the tool kit icon
Wink Savillee68857d2014-10-17 15:23:05 -07001292 intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.yes, slotId);
1293 if (mStkContext[slotId].mOpCode == OP_END_SESSION) {
1294 CatLog.d(LOG_TAG, "launchMenuActivity, return OP_END_SESSION");
1295 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
1296 if (mStkContext[slotId].mMainActivityInstance != null) {
1297 CatLog.d(LOG_TAG, "launchMenuActivity, mMainActivityInstance is not null");
1298 return;
1299 }
Wink Savillee68857d2014-10-17 15:23:05 -07001300 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001301
Wink Savillee68857d2014-10-17 15:23:05 -07001302 //If the last pending menu is secondary menu, "STATE" should be "STATE_SECONDARY".
1303 //Otherwise, it should be "STATE_MAIN".
1304 if (mStkContext[slotId].mOpCode == OP_LAUNCH_APP &&
1305 mStkContext[slotId].mMenuState == StkMenuActivity.STATE_SECONDARY) {
1306 newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
1307 } else {
1308 newIntent.putExtra("STATE", StkMenuActivity.STATE_MAIN);
1309 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
1310 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001311 } else {
1312 // We don't know and we'll let getFlagActivityNoUserAction decide.
Wink Savillee68857d2014-10-17 15:23:05 -07001313 intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001314 newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
Wink Savillee68857d2014-10-17 15:23:05 -07001315 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_SECONDARY;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001316 }
Wink Savillee68857d2014-10-17 15:23:05 -07001317 newIntent.putExtra(SLOT_ID, slotId);
1318 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001319 newIntent.setFlags(intentFlags);
1320 mContext.startActivity(newIntent);
1321 }
1322
Wink Savillee68857d2014-10-17 15:23:05 -07001323 private void launchInputActivity(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001324 Intent newIntent = new Intent(Intent.ACTION_VIEW);
Wink Savillee68857d2014-10-17 15:23:05 -07001325 String targetActivity = STK_INPUT_ACTIVITY_NAME;
1326 String uriString = STK_INPUT_URI + System.currentTimeMillis();
1327 //Set unique URI to create a new instance of activity for different slotId.
1328 Uri uriData = Uri.parse(uriString);
1329
1330 CatLog.d(LOG_TAG, "launchInputActivity, slotId: " + slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001331 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
Wink Savillee68857d2014-10-17 15:23:05 -07001332 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1333 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1334 newIntent.putExtra("INPUT", mStkContext[slotId].mCurrentCmd.geInput());
1335 newIntent.putExtra(SLOT_ID, slotId);
1336 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001337 mContext.startActivity(newIntent);
1338 }
1339
Wink Savillee68857d2014-10-17 15:23:05 -07001340 private void launchTextDialog(int slotId) {
1341 CatLog.d(LOG_TAG, "launchTextDialog, slotId: " + slotId);
1342 Intent newIntent = new Intent();
1343 String targetActivity = STK_DIALOG_ACTIVITY_NAME;
1344 int action = getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
1345 String uriString = STK_DIALOG_URI + System.currentTimeMillis();
1346 //Set unique URI to create a new instance of activity for different slotId.
1347 Uri uriData = Uri.parse(uriString);
1348 if (newIntent != null) {
1349 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1350 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1351 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
1352 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1353 newIntent.setData(uriData);
1354 newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
1355 newIntent.putExtra(SLOT_ID, slotId);
1356 startActivity(newIntent);
Preeti Ahuja414bc412013-06-25 19:31:49 -07001357 // For display texts with immediate response, send the terminal response
1358 // immediately. responseNeeded will be false, if display text command has
1359 // the immediate response tlv.
1360 if (!mStkContext[slotId].mCurrentCmd.geTextMessage().responseNeeded) {
1361 sendResponse(RES_ID_CONFIRM, slotId, true);
1362 }
Wink Savillee68857d2014-10-17 15:23:05 -07001363 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001364 }
1365
Wink Savillee68857d2014-10-17 15:23:05 -07001366 public boolean isStkDialogActivated(Context context) {
1367 String stkDialogActivity = "com.android.stk.StkDialogActivity";
1368 boolean activated = false;
1369 final ActivityManager am = (ActivityManager) context.getSystemService(
1370 Context.ACTIVITY_SERVICE);
1371 String topActivity = am.getRunningTasks(1).get(0).topActivity.getClassName();
1372
1373 CatLog.d(LOG_TAG, "isStkDialogActivated: " + topActivity);
1374 if (topActivity.equals(stkDialogActivity)) {
1375 activated = true;
1376 }
1377 CatLog.d(LOG_TAG, "activated : " + activated);
1378 return activated;
Johan Hellman3aec01c2011-02-10 10:15:28 +01001379 }
1380
Preeti Ahuja95919342013-10-01 18:18:55 -07001381 private void sendSetUpEventResponse(int event, byte[] addedInfo, int slotId) {
Preeti Ahuja414bc412013-06-25 19:31:49 -07001382 CatLog.d(this, "sendSetUpEventResponse: event : " + event + "slotId = " + slotId);
Preeti Ahuja95919342013-10-01 18:18:55 -07001383
1384 if (mStkContext[slotId].mCurrentSetupEventCmd == null){
1385 CatLog.e(this, "mCurrentSetupEventCmd is null");
1386 return;
1387 }
1388
1389 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentSetupEventCmd);
1390
1391 resMsg.setResultCode(ResultCode.OK);
1392 resMsg.setEventDownload(event, addedInfo);
1393
1394 mStkService[slotId].onCmdResponse(resMsg);
1395 }
1396
1397 private void checkForSetupEvent(int event, Bundle args, int slotId) {
1398 boolean eventPresent = false;
1399 byte[] addedInfo = null;
1400 CatLog.d(this, "Event :" + event);
1401
1402 if (mStkContext[slotId].mSetupEventListSettings != null) {
1403 /* Checks if the event is present in the EventList updated by last
1404 * SetupEventList Proactive Command */
1405 for (int i : mStkContext[slotId].mSetupEventListSettings.eventList) {
1406 if (event == i) {
1407 eventPresent = true;
1408 break;
1409 }
1410 }
1411
1412 /* If Event is present send the response to ICC */
1413 if (eventPresent == true) {
1414 CatLog.d(this, " Event " + event + "exists in the EventList");
1415
1416 switch (event) {
Preeti Ahuja560be362014-11-25 19:38:24 -08001417 case IDLE_SCREEN_AVAILABLE_EVENT:
1418 sendSetUpEventResponse(event, addedInfo, slotId);
1419 removeSetUpEvent(event, slotId);
1420 break;
Preeti Ahuja95919342013-10-01 18:18:55 -07001421 case LANGUAGE_SELECTION_EVENT:
1422 String language = mContext
1423 .getResources().getConfiguration().locale.getLanguage();
1424 CatLog.d(this, "language: " + language);
1425 // Each language code is a pair of alpha-numeric characters.
1426 // Each alpha-numeric character shall be coded on one byte
1427 // using the SMS default 7-bit coded alphabet
1428 addedInfo = GsmAlphabet.stringToGsm8BitPacked(language);
1429 sendSetUpEventResponse(event, addedInfo, slotId);
1430 break;
1431 default:
1432 break;
1433 }
1434 } else {
1435 CatLog.e(this, " Event does not exist in the EventList");
1436 }
1437 } else {
1438 CatLog.e(this, "SetupEventList is not received. Ignoring the event: " + event);
1439 }
1440 }
1441
1442 private void removeSetUpEvent(int event, int slotId) {
1443 CatLog.d(this, "Remove Event :" + event);
1444
1445 if (mStkContext[slotId].mSetupEventListSettings != null) {
1446 /*
1447 * Make new Eventlist without the event
1448 */
1449 for (int i = 0; i < mStkContext[slotId].mSetupEventListSettings.eventList.length; i++) {
1450 if (event == mStkContext[slotId].mSetupEventListSettings.eventList[i]) {
1451 mStkContext[slotId].mSetupEventListSettings.eventList[i] = INVALID_SETUP_EVENT;
1452 break;
1453 }
1454 }
1455 }
1456 }
1457
1458 private void launchEventMessage(int slotId) {
1459 launchEventMessage(slotId, mStkContext[slotId].mCurrentCmd.geTextMessage());
1460 }
1461
Wink Savillee68857d2014-10-17 15:23:05 -07001462 private void launchEventMessage(int slotId, TextMessage msg) {
1463 if (msg == null || (msg.text != null && msg.text.length() == 0)) {
1464 CatLog.d(LOG_TAG, "launchEventMessage return");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001465 return;
1466 }
Wink Savillee68857d2014-10-17 15:23:05 -07001467
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001468 Toast toast = new Toast(mContext.getApplicationContext());
1469 LayoutInflater inflate = (LayoutInflater) mContext
1470 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
1471 View v = inflate.inflate(R.layout.stk_event_msg, null);
1472 TextView tv = (TextView) v
1473 .findViewById(com.android.internal.R.id.message);
1474 ImageView iv = (ImageView) v
1475 .findViewById(com.android.internal.R.id.icon);
1476 if (msg.icon != null) {
1477 iv.setImageBitmap(msg.icon);
1478 } else {
1479 iv.setVisibility(View.GONE);
1480 }
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301481 /* In case of 'self explanatory' stkapp should display the specified
1482 * icon in proactive command (but not the alpha string).
1483 * If icon is non-self explanatory and if the icon could not be displayed
1484 * then alpha string or text data should be displayed
1485 * Ref: ETSI 102.223,section 6.5.4
1486 */
1487 if (mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ||
1488 msg.icon == null || !msg.iconSelfExplanatory) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001489 tv.setText(msg.text);
1490 }
1491
1492 toast.setView(v);
1493 toast.setDuration(Toast.LENGTH_LONG);
1494 toast.setGravity(Gravity.BOTTOM, 0, 0);
1495 toast.show();
1496 }
1497
Wink Savillee68857d2014-10-17 15:23:05 -07001498 private void launchConfirmationDialog(TextMessage msg, int slotId) {
1499 msg.title = mStkContext[slotId].lastSelectedItem;
1500 Intent newIntent = new Intent();
1501 String targetActivity = STK_DIALOG_ACTIVITY_NAME;
1502 String uriString = STK_DIALOG_URI + System.currentTimeMillis();
1503 //Set unique URI to create a new instance of activity for different slotId.
1504 Uri uriData = Uri.parse(uriString);
1505
1506 if (newIntent != null) {
1507 newIntent.setClassName(this, targetActivity);
1508 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1509 | Intent.FLAG_ACTIVITY_NO_HISTORY
1510 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
1511 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1512 newIntent.putExtra("TEXT", msg);
1513 newIntent.putExtra(SLOT_ID, slotId);
1514 newIntent.setData(uriData);
1515 startActivity(newIntent);
1516 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001517 }
1518
1519 private void launchBrowser(BrowserSettings settings) {
1520 if (settings == null) {
1521 return;
1522 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001523
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001524 Uri data = null;
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07001525 String url;
1526 if (settings.url == null) {
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001527 // if the command did not contain a URL,
1528 // launch the browser to the default homepage.
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07001529 CatLog.d(this, "no url data provided by proactive command." +
1530 " launching browser with stk default URL ... ");
1531 url = SystemProperties.get(STK_BROWSER_DEFAULT_URL_SYSPROP,
1532 "http://www.google.com");
1533 } else {
1534 CatLog.d(this, "launch browser command has attached url = " + settings.url);
1535 url = settings.url;
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001536 }
David Brown7c03cfe2011-10-20 15:36:12 -07001537
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07001538 if (url.startsWith("http://") || url.startsWith("https://")) {
1539 data = Uri.parse(url);
1540 CatLog.d(this, "launching browser with url = " + url);
1541 } else {
1542 String modifiedUrl = "http://" + url;
1543 data = Uri.parse(modifiedUrl);
1544 CatLog.d(this, "launching browser with modified url = " + modifiedUrl);
1545 }
1546
1547 Intent intent = new Intent(Intent.ACTION_VIEW);
1548 intent.setData(data);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001549 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1550 switch (settings.mode) {
1551 case USE_EXISTING_BROWSER:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001552 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1553 break;
1554 case LAUNCH_NEW_BROWSER:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001555 intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
1556 break;
1557 case LAUNCH_IF_NOT_ALREADY_LAUNCHED:
1558 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1559 break;
1560 }
1561 // start browser activity
1562 startActivity(intent);
1563 // a small delay, let the browser start, before processing the next command.
Wink Saville79085fc2009-06-09 10:27:23 -07001564 // this is good for scenarios where a related DISPLAY TEXT command is
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001565 // followed immediately.
1566 try {
Ryuto Sawada350aaa62016-06-13 14:47:22 +09001567 Thread.sleep(3000);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001568 } catch (InterruptedException e) {}
1569 }
1570
Wink Savillee68857d2014-10-17 15:23:05 -07001571 private void launchIdleText(int slotId) {
Preeti Ahuja560be362014-11-25 19:38:24 -08001572 TextMessage msg = mStkContext[slotId].mIdleModeTextCmd.geTextMessage();
dujin.cha2a0eb2a2011-11-11 15:03:57 +09001573
Preeti Ahuja95919342013-10-01 18:18:55 -07001574 if (msg == null || msg.text ==null) {
1575 CatLog.d(LOG_TAG, msg == null ? "mCurrent.getTextMessage is NULL"
1576 : "mCurrent.getTextMessage.text is NULL");
Wink Savillee68857d2014-10-17 15:23:05 -07001577 mNotificationManager.cancel(getNotificationId(slotId));
Wink Saville046db4b2011-11-01 20:42:54 -07001578 return;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001579 } else {
Preeti Ahuja95919342013-10-01 18:18:55 -07001580 CatLog.d(LOG_TAG, "launchIdleText - text[" + msg.text
1581 + "] iconSelfExplanatory[" + msg.iconSelfExplanatory
1582 + "] icon[" + msg.icon + "], sim id: " + slotId);
Wink Savillee68857d2014-10-17 15:23:05 -07001583 CatLog.d(LOG_TAG, "Add IdleMode text");
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001584 PendingIntent pendingIntent = PendingIntent.getService(mContext, 0,
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001585 new Intent(mContext, StkAppService.class), 0);
1586
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001587 final Notification.Builder notificationBuilder = new Notification.Builder(
1588 StkAppService.this);
Wink Savillee68857d2014-10-17 15:23:05 -07001589 if (mStkContext[slotId].mMainCmd != null &&
1590 mStkContext[slotId].mMainCmd.getMenu() != null) {
1591 notificationBuilder.setContentTitle(mStkContext[slotId].mMainCmd.getMenu().title);
Christopher Posselwhite2ad2ab72013-05-27 07:51:06 +02001592 } else {
1593 notificationBuilder.setContentTitle("");
1594 }
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001595 notificationBuilder
1596 .setSmallIcon(com.android.internal.R.drawable.stat_notify_sim_toolkit);
1597 notificationBuilder.setContentIntent(pendingIntent);
1598 notificationBuilder.setOngoing(true);
1599 // Set text and icon for the status bar and notification body.
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301600 if (mStkContext[slotId].mIdleModeTextCmd.hasIconLoadFailed() ||
1601 !msg.iconSelfExplanatory) {
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001602 notificationBuilder.setContentText(msg.text);
Christopher Posselwhite2ad2ab72013-05-27 07:51:06 +02001603 notificationBuilder.setTicker(msg.text);
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001604 }
1605 if (msg.icon != null) {
1606 notificationBuilder.setLargeIcon(msg.icon);
1607 } else {
1608 Bitmap bitmapIcon = BitmapFactory.decodeResource(StkAppService.this
1609 .getResources().getSystem(),
1610 com.android.internal.R.drawable.stat_notify_sim_toolkit);
1611 notificationBuilder.setLargeIcon(bitmapIcon);
1612 }
Selim Cinek62eb3fe2014-08-27 17:52:23 +02001613 notificationBuilder.setColor(mContext.getResources().getColor(
1614 com.android.internal.R.color.system_notification_accent_color));
Wink Savillee68857d2014-10-17 15:23:05 -07001615 mNotificationManager.notify(getNotificationId(slotId), notificationBuilder.build());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001616 }
1617 }
1618
Wink Savillee68857d2014-10-17 15:23:05 -07001619 private void launchToneDialog(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001620 Intent newIntent = new Intent(this, ToneDialog.class);
Wink Savillee68857d2014-10-17 15:23:05 -07001621 String uriString = STK_TONE_URI + slotId;
1622 Uri uriData = Uri.parse(uriString);
1623 //Set unique URI to create a new instance of activity for different slotId.
1624 CatLog.d(LOG_TAG, "launchToneDialog, slotId: " + slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001625 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1626 | Intent.FLAG_ACTIVITY_NO_HISTORY
1627 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
Wink Savillee68857d2014-10-17 15:23:05 -07001628 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1629 newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
1630 newIntent.putExtra("TONE", mStkContext[slotId].mCurrentCmd.getToneSettings());
1631 newIntent.putExtra(SLOT_ID, slotId);
1632 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001633 startActivity(newIntent);
1634 }
1635
Takanori Nakano49b12722016-02-16 14:34:14 +09001636 private void launchOpenChannelDialog(final int slotId) {
Wink Savillee68857d2014-10-17 15:23:05 -07001637 TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001638 if (msg == null) {
Wink Savillee68857d2014-10-17 15:23:05 -07001639 CatLog.d(LOG_TAG, "msg is null, return here");
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001640 return;
1641 }
1642
1643 msg.title = getResources().getString(R.string.stk_dialog_title);
1644 if (msg.text == null) {
1645 msg.text = getResources().getString(R.string.default_open_channel_msg);
1646 }
1647
1648 final AlertDialog dialog = new AlertDialog.Builder(mContext)
1649 .setIconAttribute(android.R.attr.alertDialogIcon)
1650 .setTitle(msg.title)
1651 .setMessage(msg.text)
1652 .setCancelable(false)
1653 .setPositiveButton(getResources().getString(R.string.stk_dialog_accept),
1654 new DialogInterface.OnClickListener() {
1655 public void onClick(DialogInterface dialog, int which) {
1656 Bundle args = new Bundle();
1657 args.putInt(RES_ID, RES_ID_CHOICE);
1658 args.putInt(CHOICE, YES);
1659 Message message = mServiceHandler.obtainMessage();
1660 message.arg1 = OP_RESPONSE;
Takanori Nakano49b12722016-02-16 14:34:14 +09001661 message.arg2 = slotId;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001662 message.obj = args;
1663 mServiceHandler.sendMessage(message);
1664 }
1665 })
1666 .setNegativeButton(getResources().getString(R.string.stk_dialog_reject),
1667 new DialogInterface.OnClickListener() {
1668 public void onClick(DialogInterface dialog, int which) {
1669 Bundle args = new Bundle();
1670 args.putInt(RES_ID, RES_ID_CHOICE);
1671 args.putInt(CHOICE, NO);
1672 Message message = mServiceHandler.obtainMessage();
1673 message.arg1 = OP_RESPONSE;
Takanori Nakano49b12722016-02-16 14:34:14 +09001674 message.arg2 = slotId;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001675 message.obj = args;
1676 mServiceHandler.sendMessage(message);
1677 }
1678 })
1679 .create();
1680
1681 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1682 if (!mContext.getResources().getBoolean(
1683 com.android.internal.R.bool.config_sf_slowBlur)) {
1684 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
1685 }
1686
1687 dialog.show();
1688 }
1689
Wink Savillee68857d2014-10-17 15:23:05 -07001690 private void launchTransientEventMessage(int slotId) {
1691 TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001692 if (msg == null) {
Wink Savillee68857d2014-10-17 15:23:05 -07001693 CatLog.d(LOG_TAG, "msg is null, return here");
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001694 return;
1695 }
1696
1697 msg.title = getResources().getString(R.string.stk_dialog_title);
1698
1699 final AlertDialog dialog = new AlertDialog.Builder(mContext)
1700 .setIconAttribute(android.R.attr.alertDialogIcon)
1701 .setTitle(msg.title)
1702 .setMessage(msg.text)
1703 .setCancelable(false)
1704 .setPositiveButton(getResources().getString(android.R.string.ok),
1705 new DialogInterface.OnClickListener() {
1706 public void onClick(DialogInterface dialog, int which) {
1707 }
1708 })
1709 .create();
1710
1711 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1712 if (!mContext.getResources().getBoolean(
1713 com.android.internal.R.bool.config_sf_slowBlur)) {
1714 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
1715 }
1716
1717 dialog.show();
1718 }
1719
Wink Savillee68857d2014-10-17 15:23:05 -07001720 private int getNotificationId(int slotId) {
1721 int notifyId = STK_NOTIFICATION_ID;
1722 if (slotId >= 0 && slotId < mSimCount) {
1723 notifyId += slotId;
1724 } else {
1725 CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
1726 }
1727 CatLog.d(LOG_TAG, "getNotificationId, slotId: " + slotId + ", notifyId: " + notifyId);
1728 return notifyId;
1729 }
1730
1731 private String getItemName(int itemId, int slotId) {
1732 Menu menu = mStkContext[slotId].mCurrentCmd.getMenu();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001733 if (menu == null) {
1734 return null;
1735 }
1736 for (Item item : menu.items) {
1737 if (item.id == itemId) {
1738 return item.text;
1739 }
1740 }
1741 return null;
1742 }
1743
Wink Savillee68857d2014-10-17 15:23:05 -07001744 private boolean removeMenu(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001745 try {
Wink Savillee68857d2014-10-17 15:23:05 -07001746 if (mStkContext[slotId].mCurrentMenu.items.size() == 1 &&
1747 mStkContext[slotId].mCurrentMenu.items.get(0) == null) {
1748 mStkContext[slotId].mSetupMenuState = STATE_NOT_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001749 return true;
1750 }
1751 } catch (NullPointerException e) {
Wink Savillee68857d2014-10-17 15:23:05 -07001752 CatLog.d(LOG_TAG, "Unable to get Menu's items size");
1753 mStkContext[slotId].mSetupMenuState = STATE_NOT_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001754 return true;
1755 }
Wink Savillee68857d2014-10-17 15:23:05 -07001756 mStkContext[slotId].mSetupMenuState = STATE_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001757 return false;
1758 }
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +05301759
Wink Savillee68857d2014-10-17 15:23:05 -07001760 StkContext getStkContext(int slotId) {
1761 if (slotId >= 0 && slotId < mSimCount) {
1762 return mStkContext[slotId];
1763 } else {
1764 CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
1765 return null;
1766 }
1767 }
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +05301768
1769 private void handleAlphaNotify(Bundle args) {
1770 String alphaString = args.getString(AppInterface.ALPHA_STRING);
1771
1772 CatLog.d(this, "Alpha string received from card: " + alphaString);
1773 Toast toast = Toast.makeText(sInstance, alphaString, Toast.LENGTH_LONG);
1774 toast.setGravity(Gravity.TOP, 0, 0);
1775 toast.show();
1776 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001777}