blob: 0033662fdd50ceaf7d873fc23d045ea92a76f226 [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;
fionaxu2c91c752017-04-21 18:11:57 -070023import android.app.NotificationChannel;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080024import android.app.NotificationManager;
25import android.app.PendingIntent;
26import android.app.Service;
Wink Savillee68857d2014-10-17 15:23:05 -070027import android.app.Activity;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080028import android.content.Context;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -050029import android.content.DialogInterface;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080030import android.content.Intent;
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +010031import android.graphics.Bitmap;
32import android.graphics.BitmapFactory;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080033import android.net.Uri;
34import android.os.Bundle;
35import android.os.Handler;
36import android.os.IBinder;
37import android.os.Looper;
38import android.os.Message;
Sooraj Sasindrana4160472016-10-12 16:28:25 -070039import android.os.PersistableBundle;
Preeti Ahuja560be362014-11-25 19:38:24 -080040import android.os.PowerManager;
Preeti Ahujaa7cdca22013-10-01 18:20:56 -070041import android.os.SystemProperties;
Preeti Ahuja95919342013-10-01 18:18:55 -070042import android.provider.Settings;
Sooraj Sasindrana4160472016-10-12 16:28:25 -070043import android.telephony.CarrierConfigManager;
Wink Saville56469d52009-04-02 01:37:03 -070044import android.telephony.TelephonyManager;
Preeti Ahujaa7cdca22013-10-01 18:20:56 -070045import android.text.TextUtils;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080046import android.view.Gravity;
47import android.view.LayoutInflater;
48import android.view.View;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -050049import android.view.WindowManager;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080050import android.widget.ImageView;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080051import android.widget.TextView;
52import android.widget.Toast;
Wink Savillee68857d2014-10-17 15:23:05 -070053import android.content.IntentFilter;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080054
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070055import com.android.internal.telephony.cat.AppInterface;
Preeti Ahuja95919342013-10-01 18:18:55 -070056import com.android.internal.telephony.cat.LaunchBrowserMode;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070057import com.android.internal.telephony.cat.Menu;
58import com.android.internal.telephony.cat.Item;
59import com.android.internal.telephony.cat.ResultCode;
60import com.android.internal.telephony.cat.CatCmdMessage;
61import com.android.internal.telephony.cat.CatCmdMessage.BrowserSettings;
Preeti Ahuja95919342013-10-01 18:18:55 -070062import com.android.internal.telephony.cat.CatCmdMessage.SetupEventListSettings;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070063import com.android.internal.telephony.cat.CatLog;
64import com.android.internal.telephony.cat.CatResponseMessage;
65import com.android.internal.telephony.cat.TextMessage;
Wink Saville94e982b2014-07-11 07:38:14 -070066import com.android.internal.telephony.uicc.IccRefreshResponse;
Wink Savillee68857d2014-10-17 15:23:05 -070067import com.android.internal.telephony.PhoneConstants;
Preeti Ahuja95919342013-10-01 18:18:55 -070068import com.android.internal.telephony.GsmAlphabet;
Legler Wuaeefef52014-10-27 00:57:18 +080069import com.android.internal.telephony.cat.CatService;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080070
Preeti Ahujaa7cdca22013-10-01 18:20:56 -070071import java.util.Iterator;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080072import java.util.LinkedList;
Wink Savillee68857d2014-10-17 15:23:05 -070073import java.lang.System;
74import java.util.List;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080075
Preeti Ahuja95919342013-10-01 18:18:55 -070076import static com.android.internal.telephony.cat.CatCmdMessage.
Preeti Ahuja560be362014-11-25 19:38:24 -080077 SetupEventListConstants.IDLE_SCREEN_AVAILABLE_EVENT;
78import static com.android.internal.telephony.cat.CatCmdMessage.
Preeti Ahuja95919342013-10-01 18:18:55 -070079 SetupEventListConstants.LANGUAGE_SELECTION_EVENT;
80
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080081/**
82 * SIM toolkit application level service. Interacts with Telephopny messages,
83 * application's launch and user input from STK UI elements.
Wink Saville79085fc2009-06-09 10:27:23 -070084 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080085 */
86public class StkAppService extends Service implements Runnable {
87
88 // members
Wink Savillee68857d2014-10-17 15:23:05 -070089 protected class StkContext {
90 protected CatCmdMessage mMainCmd = null;
91 protected CatCmdMessage mCurrentCmd = null;
92 protected CatCmdMessage mCurrentMenuCmd = null;
93 protected Menu mCurrentMenu = null;
94 protected String lastSelectedItem = null;
95 protected boolean mMenuIsVisible = false;
96 protected boolean mIsInputPending = false;
97 protected boolean mIsMenuPending = false;
98 protected boolean mIsDialogPending = false;
99 protected boolean responseNeeded = true;
100 protected boolean launchBrowser = false;
101 protected BrowserSettings mBrowserSettings = null;
102 protected LinkedList<DelayedCmd> mCmdsQ = null;
103 protected boolean mCmdInProgress = false;
104 protected int mStkServiceState = STATE_UNKNOWN;
105 protected int mSetupMenuState = STATE_UNKNOWN;
106 protected int mMenuState = StkMenuActivity.STATE_INIT;
107 protected int mOpCode = -1;
108 private Activity mActivityInstance = null;
109 private Activity mDialogInstance = null;
110 private Activity mMainActivityInstance = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700111 private int mSlotId = 0;
Preeti Ahuja95919342013-10-01 18:18:55 -0700112 private SetupEventListSettings mSetupEventListSettings = null;
113 private boolean mClearSelectItem = false;
114 private boolean mDisplayTextDlgIsVisibile = false;
115 private CatCmdMessage mCurrentSetupEventCmd = null;
Preeti Ahuja560be362014-11-25 19:38:24 -0800116 private CatCmdMessage mIdleModeTextCmd = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700117 final synchronized void setPendingActivityInstance(Activity act) {
118 CatLog.d(this, "setPendingActivityInstance act : " + mSlotId + ", " + act);
119 callSetActivityInstMsg(OP_SET_ACT_INST, mSlotId, act);
120 }
121 final synchronized Activity getPendingActivityInstance() {
122 CatLog.d(this, "getPendingActivityInstance act : " + mSlotId + ", " +
123 mActivityInstance);
124 return mActivityInstance;
125 }
126 final synchronized void setPendingDialogInstance(Activity act) {
127 CatLog.d(this, "setPendingDialogInstance act : " + mSlotId + ", " + act);
128 callSetActivityInstMsg(OP_SET_DAL_INST, mSlotId, act);
129 }
130 final synchronized Activity getPendingDialogInstance() {
131 CatLog.d(this, "getPendingDialogInstance act : " + mSlotId + ", " +
132 mDialogInstance);
133 return mDialogInstance;
134 }
135 final synchronized void setMainActivityInstance(Activity act) {
136 CatLog.d(this, "setMainActivityInstance act : " + mSlotId + ", " + act);
137 callSetActivityInstMsg(OP_SET_MAINACT_INST, mSlotId, act);
138 }
139 final synchronized Activity getMainActivityInstance() {
140 CatLog.d(this, "getMainActivityInstance act : " + mSlotId + ", " +
141 mMainActivityInstance);
142 return mMainActivityInstance;
143 }
144 }
145
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800146 private volatile Looper mServiceLooper;
147 private volatile ServiceHandler mServiceHandler;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800148 private Context mContext = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800149 private NotificationManager mNotificationManager = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800150 static StkAppService sInstance = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700151 private AppInterface[] mStkService = null;
152 private StkContext[] mStkContext = null;
153 private int mSimCount = 0;
Preeti Ahuja560be362014-11-25 19:38:24 -0800154 private PowerManager mPowerManager = null;
155 private StkCmdReceiver mStkCmdReceiver = null;
Preeti Ahuja95919342013-10-01 18:18:55 -0700156
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800157 // Used for setting FLAG_ACTIVITY_NO_USER_ACTION when
158 // creating an intent.
159 private enum InitiatedByUserAction {
160 yes, // The action was started via a user initiated action
161 unknown, // Not known for sure if user initated the action
162 }
163
164 // constants
165 static final String OPCODE = "op";
166 static final String CMD_MSG = "cmd message";
167 static final String RES_ID = "response id";
168 static final String MENU_SELECTION = "menu selection";
169 static final String INPUT = "input";
170 static final String HELP = "help";
171 static final String CONFIRMATION = "confirm";
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500172 static final String CHOICE = "choice";
Wink Savillee68857d2014-10-17 15:23:05 -0700173 static final String SLOT_ID = "SLOT_ID";
174 static final String STK_CMD = "STK CMD";
175 static final String STK_DIALOG_URI = "stk://com.android.stk/dialog/";
176 static final String STK_MENU_URI = "stk://com.android.stk/menu/";
177 static final String STK_INPUT_URI = "stk://com.android.stk/input/";
178 static final String STK_TONE_URI = "stk://com.android.stk/tone/";
Preeti Ahuja95919342013-10-01 18:18:55 -0700179
180 // These below constants are used for SETUP_EVENT_LIST
181 static final String SETUP_EVENT_TYPE = "event";
182 static final String SETUP_EVENT_CAUSE = "cause";
183
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800184 // operations ids for different service functionality.
185 static final int OP_CMD = 1;
186 static final int OP_RESPONSE = 2;
187 static final int OP_LAUNCH_APP = 3;
188 static final int OP_END_SESSION = 4;
189 static final int OP_BOOT_COMPLETED = 5;
190 private static final int OP_DELAYED_MSG = 6;
Wink Saville94e982b2014-07-11 07:38:14 -0700191 static final int OP_CARD_STATUS_CHANGED = 7;
Wink Savillee68857d2014-10-17 15:23:05 -0700192 static final int OP_SET_ACT_INST = 8;
193 static final int OP_SET_DAL_INST = 9;
194 static final int OP_SET_MAINACT_INST = 10;
Preeti Ahujab3d0e612014-11-20 13:29:25 -0800195 static final int OP_LOCALE_CHANGED = 11;
196 static final int OP_ALPHA_NOTIFY = 12;
Preeti Ahuja560be362014-11-25 19:38:24 -0800197 static final int OP_IDLE_SCREEN = 13;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800198
Preeti Ahuja95919342013-10-01 18:18:55 -0700199 //Invalid SetupEvent
200 static final int INVALID_SETUP_EVENT = 0xFF;
201
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800202 // Response ids
203 static final int RES_ID_MENU_SELECTION = 11;
204 static final int RES_ID_INPUT = 12;
205 static final int RES_ID_CONFIRM = 13;
206 static final int RES_ID_DONE = 14;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500207 static final int RES_ID_CHOICE = 15;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800208
209 static final int RES_ID_TIMEOUT = 20;
210 static final int RES_ID_BACKWARD = 21;
211 static final int RES_ID_END_SESSION = 22;
212 static final int RES_ID_EXIT = 23;
213
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500214 static final int YES = 1;
215 static final int NO = 0;
216
Wink Savillee68857d2014-10-17 15:23:05 -0700217 static final int STATE_UNKNOWN = -1;
218 static final int STATE_NOT_EXIST = 0;
219 static final int STATE_EXIST = 1;
Wink Saville79085fc2009-06-09 10:27:23 -0700220
Wink Savillee68857d2014-10-17 15:23:05 -0700221 private static final String PACKAGE_NAME = "com.android.stk";
222 private static final String STK_MENU_ACTIVITY_NAME = PACKAGE_NAME + ".StkMenuActivity";
223 private static final String STK_INPUT_ACTIVITY_NAME = PACKAGE_NAME + ".StkInputActivity";
224 private static final String STK_DIALOG_ACTIVITY_NAME = PACKAGE_NAME + ".StkDialogActivity";
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800225 // Notification id used to display Idle Mode text in NotificationManager.
226 private static final int STK_NOTIFICATION_ID = 333;
fionaxu2c91c752017-04-21 18:11:57 -0700227 // Notification channel containing all mobile service messages notifications.
228 private static final String STK_NOTIFICATION_CHANNEL_ID = "mobileServiceMessages";
229
Wink Savillee68857d2014-10-17 15:23:05 -0700230 private static final String LOG_TAG = new Object(){}.getClass().getEnclosingClass().getName();
Wink Saville79085fc2009-06-09 10:27:23 -0700231
232 // Inner class used for queuing telephony messages (proactive commands,
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800233 // session end) while the service is busy processing a previous message.
234 private class DelayedCmd {
235 // members
236 int id;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700237 CatCmdMessage msg;
Wink Savillee68857d2014-10-17 15:23:05 -0700238 int slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800239
Wink Savillee68857d2014-10-17 15:23:05 -0700240 DelayedCmd(int id, CatCmdMessage msg, int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800241 this.id = id;
242 this.msg = msg;
Wink Savillee68857d2014-10-17 15:23:05 -0700243 this.slotId = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800244 }
245 }
246
Preeti Ahujaa7cdca22013-10-01 18:20:56 -0700247 // system property to set the STK specific default url for launch browser proactive cmds
248 private static final String STK_BROWSER_DEFAULT_URL_SYSPROP = "persist.radio.stk.default_url";
249
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800250 @Override
251 public void onCreate() {
Wink Savillee68857d2014-10-17 15:23:05 -0700252 CatLog.d(LOG_TAG, "onCreate()+");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800253 // Initialize members
Wink Savillee68857d2014-10-17 15:23:05 -0700254 int i = 0;
255 mContext = getBaseContext();
256 mSimCount = TelephonyManager.from(mContext).getSimCount();
257 CatLog.d(LOG_TAG, "simCount: " + mSimCount);
258 mStkService = new AppInterface[mSimCount];
259 mStkContext = new StkContext[mSimCount];
Preeti Ahuja560be362014-11-25 19:38:24 -0800260 mPowerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
261 mStkCmdReceiver = new StkCmdReceiver();
262 registerReceiver(mStkCmdReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
Wink Savillee68857d2014-10-17 15:23:05 -0700263 for (i = 0; i < mSimCount; i++) {
264 CatLog.d(LOG_TAG, "slotId: " + i);
Legler Wuaeefef52014-10-27 00:57:18 +0800265 mStkService[i] = CatService.getInstance(i);
Wink Savillee68857d2014-10-17 15:23:05 -0700266 mStkContext[i] = new StkContext();
267 mStkContext[i].mSlotId = i;
268 mStkContext[i].mCmdsQ = new LinkedList<DelayedCmd>();
269 }
270
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800271 Thread serviceThread = new Thread(null, this, "Stk App Service");
272 serviceThread.start();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800273 mNotificationManager = (NotificationManager) mContext
274 .getSystemService(Context.NOTIFICATION_SERVICE);
275 sInstance = this;
276 }
277
278 @Override
279 public void onStart(Intent intent, int startId) {
Wink Savillee68857d2014-10-17 15:23:05 -0700280 if (intent == null) {
281 CatLog.d(LOG_TAG, "StkAppService onStart intent is null so return");
Banavathu, Srinivas Naik87cda962012-07-17 15:32:44 +0530282 return;
283 }
284
Wink Savillee68857d2014-10-17 15:23:05 -0700285 Bundle args = intent.getExtras();
286 if (args == null) {
287 CatLog.d(LOG_TAG, "StkAppService onStart args is null so return");
288 return;
289 }
290
291 int op = args.getInt(OPCODE);
292 int slotId = 0;
293 int i = 0;
294 if (op != OP_BOOT_COMPLETED) {
295 slotId = args.getInt(SLOT_ID);
296 }
Cuihtlauac ALVARADObde7f032015-05-29 16:25:12 +0200297 CatLog.d(LOG_TAG, "onStart sim id: " + slotId + ", op: " + op + ", *****");
Wink Savillee68857d2014-10-17 15:23:05 -0700298 if ((slotId >= 0 && slotId < mSimCount) && mStkService[slotId] == null) {
Legler Wuaeefef52014-10-27 00:57:18 +0800299 mStkService[slotId] = CatService.getInstance(slotId);
Wink Savillee68857d2014-10-17 15:23:05 -0700300 if (mStkService[slotId] == null) {
301 CatLog.d(LOG_TAG, "mStkService is: " + mStkContext[slotId].mStkServiceState);
302 mStkContext[slotId].mStkServiceState = STATE_NOT_EXIST;
303 //Check other StkService state.
304 //If all StkServices are not available, stop itself and uninstall apk.
305 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
306 if (i != slotId
Tsukasa Goto029332b2016-10-05 17:12:06 +0900307 && (mStkService[i] != null)
Wink Savillee68857d2014-10-17 15:23:05 -0700308 && (mStkContext[i].mStkServiceState == STATE_UNKNOWN
309 || mStkContext[i].mStkServiceState == STATE_EXIST)) {
310 break;
311 }
312 }
313 } else {
314 mStkContext[slotId].mStkServiceState = STATE_EXIST;
315 }
316 if (i == mSimCount) {
317 stopSelf();
318 StkAppInstaller.unInstall(mContext);
319 return;
320 }
321 }
322
Banavathu, Srinivas Naik87cda962012-07-17 15:32:44 +0530323 waitForLooper();
John Wang62acae42009-10-08 11:20:23 -0700324
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800325 Message msg = mServiceHandler.obtainMessage();
Wink Savillee68857d2014-10-17 15:23:05 -0700326 msg.arg1 = op;
327 msg.arg2 = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800328 switch(msg.arg1) {
329 case OP_CMD:
330 msg.obj = args.getParcelable(CMD_MSG);
331 break;
332 case OP_RESPONSE:
Wink Saville94e982b2014-07-11 07:38:14 -0700333 case OP_CARD_STATUS_CHANGED:
Preeti Ahuja95919342013-10-01 18:18:55 -0700334 case OP_LOCALE_CHANGED:
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +0530335 case OP_ALPHA_NOTIFY:
Preeti Ahuja560be362014-11-25 19:38:24 -0800336 case OP_IDLE_SCREEN:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800337 msg.obj = args;
338 /* falls through */
339 case OP_LAUNCH_APP:
340 case OP_END_SESSION:
341 case OP_BOOT_COMPLETED:
342 break;
343 default:
344 return;
345 }
346 mServiceHandler.sendMessage(msg);
347 }
348
349 @Override
350 public void onDestroy() {
Wink Savillee68857d2014-10-17 15:23:05 -0700351 CatLog.d(LOG_TAG, "onDestroy()");
Preeti Ahuja560be362014-11-25 19:38:24 -0800352 if (mStkCmdReceiver != null) {
353 unregisterReceiver(mStkCmdReceiver);
354 mStkCmdReceiver = null;
355 }
356 mPowerManager = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800357 waitForLooper();
358 mServiceLooper.quit();
359 }
360
361 @Override
362 public IBinder onBind(Intent intent) {
363 return null;
364 }
365
366 public void run() {
367 Looper.prepare();
368
369 mServiceLooper = Looper.myLooper();
370 mServiceHandler = new ServiceHandler();
371
372 Looper.loop();
373 }
374
375 /*
376 * Package api used by StkMenuActivity to indicate if its on the foreground.
377 */
Wink Savillee68857d2014-10-17 15:23:05 -0700378 void indicateMenuVisibility(boolean visibility, int slotId) {
379 if (slotId >= 0 && slotId < mSimCount) {
380 mStkContext[slotId].mMenuIsVisible = visibility;
381 }
382 }
383
Preeti Ahuja95919342013-10-01 18:18:55 -0700384 /*
385 * Package api used by StkDialogActivity to indicate if its on the foreground.
386 */
387 void setDisplayTextDlgVisibility(boolean visibility, int slotId) {
388 if (slotId >= 0 && slotId < mSimCount) {
389 mStkContext[slotId].mDisplayTextDlgIsVisibile = visibility;
390 }
391 }
392
Wink Savillee68857d2014-10-17 15:23:05 -0700393 boolean isInputPending(int slotId) {
394 if (slotId >= 0 && slotId < mSimCount) {
395 CatLog.d(LOG_TAG, "isInputFinishBySrv: " + mStkContext[slotId].mIsInputPending);
396 return mStkContext[slotId].mIsInputPending;
397 }
398 return false;
399 }
400
401 boolean isMenuPending(int slotId) {
402 if (slotId >= 0 && slotId < mSimCount) {
403 CatLog.d(LOG_TAG, "isMenuPending: " + mStkContext[slotId].mIsMenuPending);
404 return mStkContext[slotId].mIsMenuPending;
405 }
406 return false;
407 }
408
409 boolean isDialogPending(int slotId) {
410 if (slotId >= 0 && slotId < mSimCount) {
411 CatLog.d(LOG_TAG, "isDialogPending: " + mStkContext[slotId].mIsDialogPending);
412 return mStkContext[slotId].mIsDialogPending;
413 }
414 return false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800415 }
416
417 /*
418 * Package api used by StkMenuActivity to get its Menu parameter.
419 */
Wink Savillee68857d2014-10-17 15:23:05 -0700420 Menu getMenu(int slotId) {
421 CatLog.d(LOG_TAG, "StkAppService, getMenu, sim id: " + slotId);
422 if (slotId >=0 && slotId < mSimCount) {
423 return mStkContext[slotId].mCurrentMenu;
424 } else {
425 return null;
426 }
427 }
428
429 /*
430 * Package api used by StkMenuActivity to get its Main Menu parameter.
431 */
432 Menu getMainMenu(int slotId) {
433 CatLog.d(LOG_TAG, "StkAppService, getMainMenu, sim id: " + slotId);
w30234a08cffe2015-02-04 15:13:25 -0800434 if (slotId >=0 && slotId < mSimCount && (mStkContext[slotId].mMainCmd != null)) {
Wink Savillee68857d2014-10-17 15:23:05 -0700435 return mStkContext[slotId].mMainCmd.getMenu();
436 } else {
437 return null;
438 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800439 }
440
441 /*
442 * Package api used by UI Activities and Dialogs to communicate directly
443 * with the service to deliver state information and parameters.
444 */
445 static StkAppService getInstance() {
446 return sInstance;
447 }
448
449 private void waitForLooper() {
450 while (mServiceHandler == null) {
451 synchronized (this) {
452 try {
453 wait(100);
454 } catch (InterruptedException e) {
455 }
456 }
457 }
458 }
459
460 private final class ServiceHandler extends Handler {
461 @Override
462 public void handleMessage(Message msg) {
Wink Savillee68857d2014-10-17 15:23:05 -0700463 if(null == msg) {
464 CatLog.d(LOG_TAG, "ServiceHandler handleMessage msg is null");
465 return;
466 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800467 int opcode = msg.arg1;
Wink Savillee68857d2014-10-17 15:23:05 -0700468 int slotId = msg.arg2;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800469
Wink Savillee68857d2014-10-17 15:23:05 -0700470 CatLog.d(LOG_TAG, "handleMessage opcode[" + opcode + "], sim id[" + slotId + "]");
471 if (opcode == OP_CMD && msg.obj != null &&
472 ((CatCmdMessage)msg.obj).getCmdType()!= null) {
473 CatLog.d(LOG_TAG, "cmdName[" + ((CatCmdMessage)msg.obj).getCmdType().name() + "]");
474 }
475 mStkContext[slotId].mOpCode = opcode;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800476 switch (opcode) {
477 case OP_LAUNCH_APP:
Wink Savillee68857d2014-10-17 15:23:05 -0700478 if (mStkContext[slotId].mMainCmd == null) {
479 CatLog.d(LOG_TAG, "mMainCmd is null");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800480 // nothing todo when no SET UP MENU command didn't arrive.
481 return;
482 }
Wink Savillee68857d2014-10-17 15:23:05 -0700483 CatLog.d(LOG_TAG, "handleMessage OP_LAUNCH_APP - mCmdInProgress[" +
484 mStkContext[slotId].mCmdInProgress + "]");
485
486 //If there is a pending activity for the slot id,
487 //just finish it and create a new one to handle the pending command.
488 cleanUpInstanceStackBySlot(slotId);
489
Wink Savillee68857d2014-10-17 15:23:05 -0700490 CatLog.d(LOG_TAG, "Current cmd type: " +
491 mStkContext[slotId].mCurrentCmd.getCmdType());
492 //Restore the last command from stack by slot id.
493 restoreInstanceFromStackBySlot(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800494 break;
495 case OP_CMD:
Wink Savillee68857d2014-10-17 15:23:05 -0700496 CatLog.d(LOG_TAG, "[OP_CMD]");
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700497 CatCmdMessage cmdMsg = (CatCmdMessage) msg.obj;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800498 // There are two types of commands:
499 // 1. Interactive - user's response is required.
500 // 2. Informative - display a message, no interaction with the user.
501 //
Wink Saville79085fc2009-06-09 10:27:23 -0700502 // Informative commands can be handled immediately without any delay.
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800503 // Interactive commands can't override each other. So if a command
504 // is already in progress, we need to queue the next command until
505 // the user has responded or a timeout expired.
506 if (!isCmdInteractive(cmdMsg)) {
Wink Savillee68857d2014-10-17 15:23:05 -0700507 handleCmd(cmdMsg, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800508 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700509 if (!mStkContext[slotId].mCmdInProgress) {
510 mStkContext[slotId].mCmdInProgress = true;
511 handleCmd((CatCmdMessage) msg.obj, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800512 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700513 CatLog.d(LOG_TAG, "[Interactive][in progress]");
514 mStkContext[slotId].mCmdsQ.addLast(new DelayedCmd(OP_CMD,
515 (CatCmdMessage) msg.obj, slotId));
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800516 }
517 }
518 break;
519 case OP_RESPONSE:
Preeti Ahuja414bc412013-06-25 19:31:49 -0700520 handleCmdResponse((Bundle) msg.obj, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800521 // call delayed commands if needed.
Wink Savillee68857d2014-10-17 15:23:05 -0700522 if (mStkContext[slotId].mCmdsQ.size() != 0) {
523 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800524 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700525 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800526 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800527 break;
528 case OP_END_SESSION:
Wink Savillee68857d2014-10-17 15:23:05 -0700529 if (!mStkContext[slotId].mCmdInProgress) {
530 mStkContext[slotId].mCmdInProgress = true;
531 handleSessionEnd(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800532 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700533 mStkContext[slotId].mCmdsQ.addLast(
534 new DelayedCmd(OP_END_SESSION, null, slotId));
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800535 }
536 break;
537 case OP_BOOT_COMPLETED:
Wink Savillee68857d2014-10-17 15:23:05 -0700538 CatLog.d(LOG_TAG, " OP_BOOT_COMPLETED");
539 int i = 0;
540 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
541 if (mStkContext[i].mMainCmd != null) {
542 break;
543 }
544 }
545 if (i == mSimCount) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800546 StkAppInstaller.unInstall(mContext);
547 }
548 break;
549 case OP_DELAYED_MSG:
Wink Savillee68857d2014-10-17 15:23:05 -0700550 handleDelayedCmd(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800551 break;
Wink Saville94e982b2014-07-11 07:38:14 -0700552 case OP_CARD_STATUS_CHANGED:
Wink Savillee68857d2014-10-17 15:23:05 -0700553 CatLog.d(LOG_TAG, "Card/Icc Status change received");
554 handleCardStatusChangeAndIccRefresh((Bundle) msg.obj, slotId);
555 break;
556 case OP_SET_ACT_INST:
557 Activity act = new Activity();
558 act = (Activity) msg.obj;
559 CatLog.d(LOG_TAG, "Set activity instance. " + act);
560 mStkContext[slotId].mActivityInstance = act;
561 break;
562 case OP_SET_DAL_INST:
563 Activity dal = new Activity();
564 CatLog.d(LOG_TAG, "Set dialog instance. " + dal);
565 dal = (Activity) msg.obj;
566 mStkContext[slotId].mDialogInstance = dal;
567 break;
568 case OP_SET_MAINACT_INST:
569 Activity mainAct = new Activity();
570 mainAct = (Activity) msg.obj;
571 CatLog.d(LOG_TAG, "Set activity instance. " + mainAct);
572 mStkContext[slotId].mMainActivityInstance = mainAct;
Wink Saville94e982b2014-07-11 07:38:14 -0700573 break;
Preeti Ahuja95919342013-10-01 18:18:55 -0700574 case OP_LOCALE_CHANGED:
575 CatLog.d(this, "Locale Changed");
Yuta Ui1481b172016-02-03 15:34:31 +0900576 for (int slot = PhoneConstants.SIM_ID_1; slot < mSimCount; slot++) {
577 checkForSetupEvent(LANGUAGE_SELECTION_EVENT, (Bundle) msg.obj, slot);
578 }
fionaxu805eb572017-05-02 10:57:30 -0700579 // rename all registered notification channels on locale change
580 createAllChannels();
Preeti Ahuja95919342013-10-01 18:18:55 -0700581 break;
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +0530582 case OP_ALPHA_NOTIFY:
583 handleAlphaNotify((Bundle) msg.obj);
584 break;
Preeti Ahuja560be362014-11-25 19:38:24 -0800585 case OP_IDLE_SCREEN:
586 for (int slot = 0; slot < mSimCount; slot++) {
587 if (mStkContext[slot] != null) {
588 handleIdleScreen(slot);
589 }
590 }
591 break;
Wink Saville94e982b2014-07-11 07:38:14 -0700592 }
593 }
594
Wink Savillee68857d2014-10-17 15:23:05 -0700595 private void handleCardStatusChangeAndIccRefresh(Bundle args, int slotId) {
Wink Saville94e982b2014-07-11 07:38:14 -0700596 boolean cardStatus = args.getBoolean(AppInterface.CARD_STATUS);
597
Wink Savillee68857d2014-10-17 15:23:05 -0700598 CatLog.d(LOG_TAG, "CardStatus: " + cardStatus);
Wink Saville94e982b2014-07-11 07:38:14 -0700599 if (cardStatus == false) {
Wink Savillee68857d2014-10-17 15:23:05 -0700600 CatLog.d(LOG_TAG, "CARD is ABSENT");
Wink Saville94e982b2014-07-11 07:38:14 -0700601 // Uninstall STKAPP, Clear Idle text, Stop StkAppService
Wink Savillee68857d2014-10-17 15:23:05 -0700602 mNotificationManager.cancel(getNotificationId(slotId));
603 if (isAllOtherCardsAbsent(slotId)) {
604 CatLog.d(LOG_TAG, "All CARDs are ABSENT");
605 StkAppInstaller.unInstall(mContext);
606 stopSelf();
607 }
Wink Saville94e982b2014-07-11 07:38:14 -0700608 } else {
609 IccRefreshResponse state = new IccRefreshResponse();
610 state.refreshResult = args.getInt(AppInterface.REFRESH_RESULT);
611
Wink Savillee68857d2014-10-17 15:23:05 -0700612 CatLog.d(LOG_TAG, "Icc Refresh Result: "+ state.refreshResult);
Wink Saville94e982b2014-07-11 07:38:14 -0700613 if ((state.refreshResult == IccRefreshResponse.REFRESH_RESULT_INIT) ||
614 (state.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET)) {
615 // Clear Idle Text
Wink Savillee68857d2014-10-17 15:23:05 -0700616 mNotificationManager.cancel(getNotificationId(slotId));
Wink Saville94e982b2014-07-11 07:38:14 -0700617 }
618
619 if (state.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET) {
620 // Uninstall STkmenu
Wink Savillee68857d2014-10-17 15:23:05 -0700621 if (isAllOtherCardsAbsent(slotId)) {
622 StkAppInstaller.unInstall(mContext);
623 }
624 mStkContext[slotId].mCurrentMenu = null;
625 mStkContext[slotId].mMainCmd = null;
Wink Saville94e982b2014-07-11 07:38:14 -0700626 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800627 }
628 }
629 }
Wink Savillee68857d2014-10-17 15:23:05 -0700630 /*
631 * Check if all SIMs are absent except the id of slot equals "slotId".
632 */
633 private boolean isAllOtherCardsAbsent(int slotId) {
634 TelephonyManager mTm = (TelephonyManager) mContext.getSystemService(
635 Context.TELEPHONY_SERVICE);
636 int i = 0;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800637
Wink Savillee68857d2014-10-17 15:23:05 -0700638 for (i = 0; i < mSimCount; i++) {
639 if (i != slotId && mTm.hasIccCard(i)) {
640 break;
641 }
642 }
643 if (i == mSimCount) {
644 return true;
645 } else {
646 return false;
647 }
648 }
Preeti Ahuja95919342013-10-01 18:18:55 -0700649
Preeti Ahuja560be362014-11-25 19:38:24 -0800650 /*
651 * If the device is not in an interactive state, we can assume
652 * that the screen is idle.
653 */
654 private boolean isScreenIdle() {
655 return (!mPowerManager.isInteractive());
656 }
657
658 private void handleIdleScreen(int slotId) {
659
660 // If the idle screen event is present in the list need to send the
661 // response to SIM.
662 CatLog.d(this, "Need to send IDLE SCREEN Available event to SIM");
663 checkForSetupEvent(IDLE_SCREEN_AVAILABLE_EVENT, null, slotId);
664
665 if (mStkContext[slotId].mIdleModeTextCmd != null) {
666 launchIdleText(slotId);
667 }
668 }
669
670 private void sendScreenBusyResponse(int slotId) {
671 if (mStkContext[slotId].mCurrentCmd == null) {
672 return;
673 }
674 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentCmd);
675 CatLog.d(this, "SCREEN_BUSY");
676 resMsg.setResultCode(ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS);
677 mStkService[slotId].onCmdResponse(resMsg);
678 if (mStkContext[slotId].mCmdsQ.size() != 0) {
679 callDelayedMsg(slotId);
680 } else {
681 mStkContext[slotId].mCmdInProgress = false;
682 }
683 }
684
Preeti Ahuja95919342013-10-01 18:18:55 -0700685 private void sendResponse(int resId, int slotId, boolean confirm) {
686 Message msg = mServiceHandler.obtainMessage();
687 msg.arg1 = OP_RESPONSE;
Takanori Nakano49b12722016-02-16 14:34:14 +0900688 msg.arg2 = slotId;
Preeti Ahuja95919342013-10-01 18:18:55 -0700689 Bundle args = new Bundle();
690 args.putInt(StkAppService.RES_ID, resId);
Preeti Ahuja95919342013-10-01 18:18:55 -0700691 args.putBoolean(StkAppService.CONFIRMATION, confirm);
692 msg.obj = args;
693 mServiceHandler.sendMessage(msg);
694 }
695
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700696 private boolean isCmdInteractive(CatCmdMessage cmd) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800697 switch (cmd.getCmdType()) {
698 case SEND_DTMF:
699 case SEND_SMS:
700 case SEND_SS:
701 case SEND_USSD:
702 case SET_UP_IDLE_MODE_TEXT:
703 case SET_UP_MENU:
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500704 case CLOSE_CHANNEL:
705 case RECEIVE_DATA:
706 case SEND_DATA:
Preeti Ahuja95919342013-10-01 18:18:55 -0700707 case SET_UP_EVENT_LIST:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800708 return false;
709 }
710
711 return true;
712 }
713
Wink Savillee68857d2014-10-17 15:23:05 -0700714 private void handleDelayedCmd(int slotId) {
715 CatLog.d(LOG_TAG, "handleDelayedCmd, slotId: " + slotId);
716 if (mStkContext[slotId].mCmdsQ.size() != 0) {
717 DelayedCmd cmd = mStkContext[slotId].mCmdsQ.poll();
718 if (cmd != null) {
719 CatLog.d(LOG_TAG, "handleDelayedCmd - queue size: " +
720 mStkContext[slotId].mCmdsQ.size() +
721 " id: " + cmd.id + "sim id: " + cmd.slotId);
722 switch (cmd.id) {
723 case OP_CMD:
724 handleCmd(cmd.msg, cmd.slotId);
725 break;
726 case OP_END_SESSION:
727 handleSessionEnd(cmd.slotId);
728 break;
729 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800730 }
731 }
732 }
733
Wink Savillee68857d2014-10-17 15:23:05 -0700734 private void callDelayedMsg(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800735 Message msg = mServiceHandler.obtainMessage();
736 msg.arg1 = OP_DELAYED_MSG;
Wink Savillee68857d2014-10-17 15:23:05 -0700737 msg.arg2 = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800738 mServiceHandler.sendMessage(msg);
739 }
740
Wink Savillee68857d2014-10-17 15:23:05 -0700741 private void callSetActivityInstMsg(int inst_type, int slotId, Object obj) {
742 Message msg = mServiceHandler.obtainMessage();
743 msg.obj = obj;
744 msg.arg1 = inst_type;
745 msg.arg2 = slotId;
746 mServiceHandler.sendMessage(msg);
747 }
748
749 private void handleSessionEnd(int slotId) {
Legler Wuaeefef52014-10-27 00:57:18 +0800750 // We should finish all pending activity if receiving END SESSION command.
751 cleanUpInstanceStackBySlot(slotId);
752
Wink Savillee68857d2014-10-17 15:23:05 -0700753 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
754 CatLog.d(LOG_TAG, "[handleSessionEnd] - mCurrentCmd changed to mMainCmd!.");
755 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mMainCmd;
756 CatLog.d(LOG_TAG, "slotId: " + slotId + ", mMenuState: " +
757 mStkContext[slotId].mMenuState);
758
759 mStkContext[slotId].mIsInputPending = false;
760 mStkContext[slotId].mIsMenuPending = false;
761 mStkContext[slotId].mIsDialogPending = false;
762
Wink Savillee68857d2014-10-17 15:23:05 -0700763 if (mStkContext[slotId].mMainCmd == null) {
764 CatLog.d(LOG_TAG, "[handleSessionEnd][mMainCmd is null!]");
765 }
766 mStkContext[slotId].lastSelectedItem = null;
Wink Saville79085fc2009-06-09 10:27:23 -0700767 // In case of SET UP MENU command which removed the app, don't
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800768 // update the current menu member.
Wink Savillee68857d2014-10-17 15:23:05 -0700769 if (mStkContext[slotId].mCurrentMenu != null && mStkContext[slotId].mMainCmd != null) {
770 mStkContext[slotId].mCurrentMenu = mStkContext[slotId].mMainCmd.getMenu();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800771 }
Wink Savillee68857d2014-10-17 15:23:05 -0700772 CatLog.d(LOG_TAG, "[handleSessionEnd][mMenuState]" + mStkContext[slotId].mMenuIsVisible);
773 // In mutiple instance architecture, the main menu for slotId will be finished when user
774 // goes to the Stk menu of the other SIM. So, we should launch a new instance for the
775 // main menu if the main menu instance has been finished.
776 // If the current menu is secondary menu, we should launch main menu.
777 if (StkMenuActivity.STATE_SECONDARY == mStkContext[slotId].mMenuState) {
778 launchMenuActivity(null, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800779 }
Wink Savillee68857d2014-10-17 15:23:05 -0700780 if (mStkContext[slotId].mCmdsQ.size() != 0) {
781 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800782 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700783 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800784 }
785 // In case a launch browser command was just confirmed, launch that url.
Wink Savillee68857d2014-10-17 15:23:05 -0700786 if (mStkContext[slotId].launchBrowser) {
787 mStkContext[slotId].launchBrowser = false;
788 launchBrowser(mStkContext[slotId].mBrowserSettings);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800789 }
790 }
791
Preeti Ahuja560be362014-11-25 19:38:24 -0800792 // returns true if any Stk related activity already has focus on the screen
793 private boolean isTopOfStack() {
pkanwareab12f32017-02-06 08:35:03 -0800794 ActivityManager mActivityManager = (ActivityManager) mContext
Preeti Ahuja560be362014-11-25 19:38:24 -0800795 .getSystemService(ACTIVITY_SERVICE);
pkanwareab12f32017-02-06 08:35:03 -0800796 String currentPackageName = null;
797 List<RunningTaskInfo> tasks = mActivityManager.getRunningTasks(1);
798 if (tasks == null || tasks.get(0).topActivity == null) {
799 return false;
800 }
801 currentPackageName = tasks.get(0).topActivity.getPackageName();
Preeti Ahuja560be362014-11-25 19:38:24 -0800802 if (null != currentPackageName) {
803 return currentPackageName.equals(PACKAGE_NAME);
804 }
Preeti Ahuja560be362014-11-25 19:38:24 -0800805 return false;
806 }
807
Sooraj Sasindrana4160472016-10-12 16:28:25 -0700808 /**
809 * Get the boolean config from carrier config manager.
810 *
811 * @param context the context to get carrier service
812 * @param key config key defined in CarrierConfigManager
813 * @return boolean value of corresponding key.
814 */
815 private static boolean getBooleanCarrierConfig(Context context, String key) {
816 CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(
817 Context.CARRIER_CONFIG_SERVICE);
818 PersistableBundle b = null;
819 if (configManager != null) {
820 b = configManager.getConfig();
821 }
822 if (b != null) {
823 return b.getBoolean(key);
824 } else {
825 // Return static default defined in CarrierConfigManager.
826 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
827 }
828 }
829
Wink Savillee68857d2014-10-17 15:23:05 -0700830 private void handleCmd(CatCmdMessage cmdMsg, int slotId) {
Preeti Ahuja95919342013-10-01 18:18:55 -0700831
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800832 if (cmdMsg == null) {
833 return;
834 }
835 // save local reference for state tracking.
Wink Savillee68857d2014-10-17 15:23:05 -0700836 mStkContext[slotId].mCurrentCmd = cmdMsg;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800837 boolean waitForUsersResponse = true;
838
Wink Savillee68857d2014-10-17 15:23:05 -0700839 mStkContext[slotId].mIsInputPending = false;
840 mStkContext[slotId].mIsMenuPending = false;
841 mStkContext[slotId].mIsDialogPending = false;
842
843 CatLog.d(LOG_TAG,"[handleCmd]" + cmdMsg.getCmdType().name());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800844 switch (cmdMsg.getCmdType()) {
845 case DISPLAY_TEXT:
846 TextMessage msg = cmdMsg.geTextMessage();
Jeevaka Badrappan854a25c2012-12-01 16:32:03 +0200847 waitForUsersResponse = msg.responseNeeded;
Wink Savillee68857d2014-10-17 15:23:05 -0700848 if (mStkContext[slotId].lastSelectedItem != null) {
849 msg.title = mStkContext[slotId].lastSelectedItem;
850 } else if (mStkContext[slotId].mMainCmd != null){
851 msg.title = mStkContext[slotId].mMainCmd.getMenu().title;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800852 } else {
853 // TODO: get the carrier name from the SIM
854 msg.title = "";
855 }
Preeti Ahuja560be362014-11-25 19:38:24 -0800856 //If we receive a low priority Display Text and the device is
857 // not displaying any STK related activity and the screen is not idle
858 // ( that is, device is in an interactive state), then send a screen busy
859 // terminal response. Otherwise display the message. The existing
860 // displayed message shall be updated with the new display text
861 // proactive command (Refer to ETSI TS 102 384 section 27.22.4.1.4.4.2).
862 if (!(msg.isHighPriority || mStkContext[slotId].mMenuIsVisible
863 || mStkContext[slotId].mDisplayTextDlgIsVisibile || isTopOfStack())) {
864 if(!isScreenIdle()) {
865 CatLog.d(LOG_TAG, "Screen is not idle");
866 sendScreenBusyResponse(slotId);
867 } else {
868 launchTextDialog(slotId);
869 }
870 } else {
871 launchTextDialog(slotId);
872 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800873 break;
874 case SELECT_ITEM:
Wink Savillee68857d2014-10-17 15:23:05 -0700875 CatLog.d(LOG_TAG, "SELECT_ITEM +");
876 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
877 mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
878 launchMenuActivity(cmdMsg.getMenu(), slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800879 break;
880 case SET_UP_MENU:
Wink Savillee68857d2014-10-17 15:23:05 -0700881 mStkContext[slotId].mCmdInProgress = false;
882 mStkContext[slotId].mMainCmd = mStkContext[slotId].mCurrentCmd;
883 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
884 mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
885 CatLog.d(LOG_TAG, "SET_UP_MENU [" + removeMenu(slotId) + "]");
886
887 if (removeMenu(slotId)) {
888 int i = 0;
889 CatLog.d(LOG_TAG, "removeMenu() - Uninstall App");
890 mStkContext[slotId].mCurrentMenu = null;
Preeti Ahuja95919342013-10-01 18:18:55 -0700891 mStkContext[slotId].mMainCmd = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700892 //Check other setup menu state. If all setup menu are removed, uninstall apk.
893 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
894 if (i != slotId
895 && (mStkContext[slotId].mSetupMenuState == STATE_UNKNOWN
896 || mStkContext[slotId].mSetupMenuState == STATE_EXIST)) {
897 CatLog.d(LOG_TAG, "Not Uninstall App:" + i + ","
898 + mStkContext[slotId].mSetupMenuState);
899 break;
900 }
901 }
902 if (i == mSimCount) {
903 StkAppInstaller.unInstall(mContext);
904 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800905 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700906 CatLog.d(LOG_TAG, "install App");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800907 StkAppInstaller.install(mContext);
908 }
Wink Savillee68857d2014-10-17 15:23:05 -0700909 if (mStkContext[slotId].mMenuIsVisible) {
910 launchMenuActivity(null, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800911 }
912 break;
913 case GET_INPUT:
914 case GET_INKEY:
Wink Savillee68857d2014-10-17 15:23:05 -0700915 launchInputActivity(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800916 break;
917 case SET_UP_IDLE_MODE_TEXT:
918 waitForUsersResponse = false;
Preeti Ahuja560be362014-11-25 19:38:24 -0800919 mStkContext[slotId].mIdleModeTextCmd = mStkContext[slotId].mCurrentCmd;
920 TextMessage idleModeText = mStkContext[slotId].mCurrentCmd.geTextMessage();
921 if (idleModeText == null) {
922 launchIdleText(slotId);
923 mStkContext[slotId].mIdleModeTextCmd = null;
924 }
925 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
926 if ((mStkContext[slotId].mIdleModeTextCmd != null) && isScreenIdle()) {
927 CatLog.d(this, "set up idle mode");
928 launchIdleText(slotId);
929 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800930 break;
931 case SEND_DTMF:
932 case SEND_SMS:
933 case SEND_SS:
934 case SEND_USSD:
Preeti Ahuja95919342013-10-01 18:18:55 -0700935 case GET_CHANNEL_STATUS:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800936 waitForUsersResponse = false;
Wink Savillee68857d2014-10-17 15:23:05 -0700937 launchEventMessage(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800938 break;
939 case LAUNCH_BROWSER:
Ryuto Sawada0bdc7192016-04-18 12:10:56 +0900940 // The device setup process should not be interrupted by launching browser.
941 if (Settings.Global.getInt(mContext.getContentResolver(),
942 Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
943 CatLog.d(this, "The command is not performed if the setup has not been completed.");
944 sendScreenBusyResponse(slotId);
945 break;
946 }
Sooraj Sasindrana4160472016-10-12 16:28:25 -0700947
948 /* Check if Carrier would not want to launch browser */
949 if (getBooleanCarrierConfig(mContext,
950 CarrierConfigManager.KEY_STK_DISABLE_LAUNCH_BROWSER_BOOL)) {
951 CatLog.d(this, "Browser is not launched as per carrier.");
952 sendResponse(RES_ID_DONE, slotId, true);
953 break;
954 }
955
Preeti Ahujaa7cdca22013-10-01 18:20:56 -0700956 TextMessage alphaId = mStkContext[slotId].mCurrentCmd.geTextMessage();
957 if ((mStkContext[slotId].mCurrentCmd.getBrowserSettings().mode
958 == LaunchBrowserMode.LAUNCH_IF_NOT_ALREADY_LAUNCHED) &&
959 ((alphaId == null) || TextUtils.isEmpty(alphaId.text))) {
960 // don't need user confirmation in this case
961 // just launch the browser or spawn a new tab
962 CatLog.d(this, "Browser mode is: launch if not already launched " +
963 "and user confirmation is not currently needed.\n" +
964 "supressing confirmation dialogue and confirming silently...");
965 mStkContext[slotId].launchBrowser = true;
966 mStkContext[slotId].mBrowserSettings =
967 mStkContext[slotId].mCurrentCmd.getBrowserSettings();
968 sendResponse(RES_ID_CONFIRM, slotId, true);
969 } else {
970 launchConfirmationDialog(alphaId, slotId);
971 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800972 break;
973 case SET_UP_CALL:
Preeti Ahujadd240102013-08-30 17:25:06 -0700974 TextMessage mesg = mStkContext[slotId].mCurrentCmd.getCallSettings().confirmMsg;
975 if((mesg != null) && (mesg.text == null || mesg.text.length() == 0)) {
976 mesg.text = getResources().getString(R.string.default_setup_call_msg);
977 }
978 CatLog.d(this, "SET_UP_CALL mesg.text " + mesg.text);
979 launchConfirmationDialog(mesg, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800980 break;
981 case PLAY_TONE:
Wink Savillee68857d2014-10-17 15:23:05 -0700982 launchToneDialog(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800983 break;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500984 case OPEN_CHANNEL:
Wink Savillee68857d2014-10-17 15:23:05 -0700985 launchOpenChannelDialog(slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500986 break;
987 case CLOSE_CHANNEL:
988 case RECEIVE_DATA:
989 case SEND_DATA:
Wink Savillee68857d2014-10-17 15:23:05 -0700990 TextMessage m = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500991
992 if ((m != null) && (m.text == null)) {
993 switch(cmdMsg.getCmdType()) {
994 case CLOSE_CHANNEL:
995 m.text = getResources().getString(R.string.default_close_channel_msg);
996 break;
997 case RECEIVE_DATA:
998 m.text = getResources().getString(R.string.default_receive_data_msg);
999 break;
1000 case SEND_DATA:
1001 m.text = getResources().getString(R.string.default_send_data_msg);
1002 break;
1003 }
1004 }
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001005 /*
1006 * Display indication in the form of a toast to the user if required.
1007 */
Wink Savillee68857d2014-10-17 15:23:05 -07001008 launchEventMessage(slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001009 break;
Preeti Ahuja95919342013-10-01 18:18:55 -07001010 case SET_UP_EVENT_LIST:
1011 mStkContext[slotId].mSetupEventListSettings =
1012 mStkContext[slotId].mCurrentCmd.getSetEventList();
1013 mStkContext[slotId].mCurrentSetupEventCmd = mStkContext[slotId].mCurrentCmd;
1014 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
Preeti Ahuja560be362014-11-25 19:38:24 -08001015 if (isScreenIdle()) {
1016 CatLog.d(this," Check if IDLE_SCREEN_AVAILABLE_EVENT is present in List");
1017 checkForSetupEvent(IDLE_SCREEN_AVAILABLE_EVENT, null, slotId);
1018 }
Preeti Ahuja95919342013-10-01 18:18:55 -07001019 break;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001020 }
1021
1022 if (!waitForUsersResponse) {
Wink Savillee68857d2014-10-17 15:23:05 -07001023 if (mStkContext[slotId].mCmdsQ.size() != 0) {
1024 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001025 } else {
Wink Savillee68857d2014-10-17 15:23:05 -07001026 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001027 }
1028 }
1029 }
1030
Wink Savillee68857d2014-10-17 15:23:05 -07001031 private void handleCmdResponse(Bundle args, int slotId) {
1032 CatLog.d(LOG_TAG, "handleCmdResponse, sim id: " + slotId);
1033 if (mStkContext[slotId].mCurrentCmd == null) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001034 return;
1035 }
Wink Savillee68857d2014-10-17 15:23:05 -07001036
1037 if (mStkService[slotId] == null) {
Legler Wuaeefef52014-10-27 00:57:18 +08001038 mStkService[slotId] = CatService.getInstance(slotId);
Wink Savillee68857d2014-10-17 15:23:05 -07001039 if (mStkService[slotId] == null) {
Alex Yakavenkad8e2ecd2012-04-20 17:10:15 -07001040 // This should never happen (we should be responding only to a message
1041 // that arrived from StkService). It has to exist by this time
Wink Savillee68857d2014-10-17 15:23:05 -07001042 CatLog.d(LOG_TAG, "Exception! mStkService is null when we need to send response.");
Alex Yakavenkad8e2ecd2012-04-20 17:10:15 -07001043 throw new RuntimeException("mStkService is null when we need to send response");
1044 }
1045 }
1046
Wink Savillee68857d2014-10-17 15:23:05 -07001047 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentCmd);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001048
1049 // set result code
1050 boolean helpRequired = args.getBoolean(HELP, false);
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001051 boolean confirmed = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001052
1053 switch(args.getInt(RES_ID)) {
1054 case RES_ID_MENU_SELECTION:
Wink Savillee68857d2014-10-17 15:23:05 -07001055 CatLog.d(LOG_TAG, "MENU_SELECTION=" + mStkContext[slotId].
1056 mCurrentMenuCmd.getCmdType());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001057 int menuSelection = args.getInt(MENU_SELECTION);
Wink Savillee68857d2014-10-17 15:23:05 -07001058 switch(mStkContext[slotId].mCurrentMenuCmd.getCmdType()) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001059 case SET_UP_MENU:
1060 case SELECT_ITEM:
Wink Savillee68857d2014-10-17 15:23:05 -07001061 mStkContext[slotId].lastSelectedItem = getItemName(menuSelection, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001062 if (helpRequired) {
1063 resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
1064 } else {
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301065 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1066 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001067 }
1068 resMsg.setMenuSelection(menuSelection);
1069 break;
1070 }
1071 break;
1072 case RES_ID_INPUT:
Wink Savillee68857d2014-10-17 15:23:05 -07001073 CatLog.d(LOG_TAG, "RES_ID_INPUT");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001074 String input = args.getString(INPUT);
Wink Savillee68857d2014-10-17 15:23:05 -07001075 if (input != null && (null != mStkContext[slotId].mCurrentCmd.geInput()) &&
1076 (mStkContext[slotId].mCurrentCmd.geInput().yesNo)) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001077 boolean yesNoSelection = input
1078 .equals(StkInputActivity.YES_STR_RESPONSE);
1079 resMsg.setYesNo(yesNoSelection);
1080 } else {
1081 if (helpRequired) {
1082 resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
1083 } else {
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301084 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1085 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001086 resMsg.setInput(input);
1087 }
1088 }
1089 break;
1090 case RES_ID_CONFIRM:
Alex Yakavenkad41f1d92010-07-12 14:13:13 -07001091 CatLog.d(this, "RES_ID_CONFIRM");
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001092 confirmed = args.getBoolean(CONFIRMATION);
Wink Savillee68857d2014-10-17 15:23:05 -07001093 switch (mStkContext[slotId].mCurrentCmd.getCmdType()) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001094 case DISPLAY_TEXT:
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301095 if (confirmed) {
1096 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1097 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
1098 } else {
1099 resMsg.setResultCode(ResultCode.UICC_SESSION_TERM_BY_USER);
1100 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001101 break;
1102 case LAUNCH_BROWSER:
1103 resMsg.setResultCode(confirmed ? ResultCode.OK
1104 : ResultCode.UICC_SESSION_TERM_BY_USER);
1105 if (confirmed) {
Wink Savillee68857d2014-10-17 15:23:05 -07001106 mStkContext[slotId].launchBrowser = true;
1107 mStkContext[slotId].mBrowserSettings =
1108 mStkContext[slotId].mCurrentCmd.getBrowserSettings();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001109 }
1110 break;
1111 case SET_UP_CALL:
1112 resMsg.setResultCode(ResultCode.OK);
1113 resMsg.setConfirmation(confirmed);
1114 if (confirmed) {
Wink Savillee68857d2014-10-17 15:23:05 -07001115 launchEventMessage(slotId,
1116 mStkContext[slotId].mCurrentCmd.getCallSettings().callMsg);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001117 }
1118 break;
1119 }
1120 break;
1121 case RES_ID_DONE:
1122 resMsg.setResultCode(ResultCode.OK);
1123 break;
1124 case RES_ID_BACKWARD:
Wink Savillee68857d2014-10-17 15:23:05 -07001125 CatLog.d(LOG_TAG, "RES_ID_BACKWARD");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001126 resMsg.setResultCode(ResultCode.BACKWARD_MOVE_BY_USER);
1127 break;
1128 case RES_ID_END_SESSION:
Wink Savillee68857d2014-10-17 15:23:05 -07001129 CatLog.d(LOG_TAG, "RES_ID_END_SESSION");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001130 resMsg.setResultCode(ResultCode.UICC_SESSION_TERM_BY_USER);
1131 break;
1132 case RES_ID_TIMEOUT:
Wink Savillee68857d2014-10-17 15:23:05 -07001133 CatLog.d(LOG_TAG, "RES_ID_TIMEOUT");
Naveen Kallad5176892009-11-30 12:45:29 -08001134 // GCF test-case 27.22.4.1.1 Expected Sequence 1.5 (DISPLAY TEXT,
1135 // Clear message after delay, successful) expects result code OK.
1136 // If the command qualifier specifies no user response is required
1137 // then send OK instead of NO_RESPONSE_FROM_USER
Wink Savillee68857d2014-10-17 15:23:05 -07001138 if ((mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1139 AppInterface.CommandType.DISPLAY_TEXT.value())
1140 && (mStkContext[slotId].mCurrentCmd.geTextMessage().userClear == false)) {
Naveen Kallad5176892009-11-30 12:45:29 -08001141 resMsg.setResultCode(ResultCode.OK);
1142 } else {
1143 resMsg.setResultCode(ResultCode.NO_RESPONSE_FROM_USER);
1144 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001145 break;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001146 case RES_ID_CHOICE:
1147 int choice = args.getInt(CHOICE);
1148 CatLog.d(this, "User Choice=" + choice);
1149 switch (choice) {
1150 case YES:
1151 resMsg.setResultCode(ResultCode.OK);
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001152 confirmed = true;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001153 break;
1154 case NO:
1155 resMsg.setResultCode(ResultCode.USER_NOT_ACCEPT);
1156 break;
1157 }
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001158
Wink Savillee68857d2014-10-17 15:23:05 -07001159 if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1160 AppInterface.CommandType.OPEN_CHANNEL.value()) {
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001161 resMsg.setConfirmation(confirmed);
1162 }
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001163 break;
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001164
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001165 default:
Wink Savillee68857d2014-10-17 15:23:05 -07001166 CatLog.d(LOG_TAG, "Unknown result id");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001167 return;
1168 }
Wink Savillee68857d2014-10-17 15:23:05 -07001169
1170 if (null != mStkContext[slotId].mCurrentCmd &&
1171 null != mStkContext[slotId].mCurrentCmd.getCmdType()) {
1172 CatLog.d(LOG_TAG, "handleCmdResponse- cmdName[" +
1173 mStkContext[slotId].mCurrentCmd.getCmdType().name() + "]");
1174 }
1175 mStkService[slotId].onCmdResponse(resMsg);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001176 }
1177
1178 /**
1179 * Returns 0 or FLAG_ACTIVITY_NO_USER_ACTION, 0 means the user initiated the action.
1180 *
1181 * @param userAction If the userAction is yes then we always return 0 otherwise
1182 * mMenuIsVisible is used to determine what to return. If mMenuIsVisible is true
1183 * then we are the foreground app and we'll return 0 as from our perspective a
1184 * user action did cause. If it's false than we aren't the foreground app and
1185 * FLAG_ACTIVITY_NO_USER_ACTION is returned.
Wink Saville79085fc2009-06-09 10:27:23 -07001186 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001187 * @return 0 or FLAG_ACTIVITY_NO_USER_ACTION
1188 */
Wink Savillee68857d2014-10-17 15:23:05 -07001189 private int getFlagActivityNoUserAction(InitiatedByUserAction userAction, int slotId) {
1190 return ((userAction == InitiatedByUserAction.yes) | mStkContext[slotId].mMenuIsVisible)
1191 ? 0 : Intent.FLAG_ACTIVITY_NO_USER_ACTION;
1192 }
1193 /**
1194 * This method is used for cleaning up pending instances in stack.
1195 */
1196 private void cleanUpInstanceStackBySlot(int slotId) {
1197 Activity activity = mStkContext[slotId].getPendingActivityInstance();
1198 Activity dialog = mStkContext[slotId].getPendingDialogInstance();
1199 CatLog.d(LOG_TAG, "cleanUpInstanceStackBySlot slotId: " + slotId);
Legler Wuaeefef52014-10-27 00:57:18 +08001200 if (mStkContext[slotId].mCurrentCmd == null) {
1201 CatLog.d(LOG_TAG, "current cmd is null.");
1202 return;
1203 }
Wink Savillee68857d2014-10-17 15:23:05 -07001204 if (activity != null) {
1205 CatLog.d(LOG_TAG, "current cmd type: " +
1206 mStkContext[slotId].mCurrentCmd.getCmdType());
1207 if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1208 AppInterface.CommandType.GET_INPUT.value() ||
1209 mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1210 AppInterface.CommandType.GET_INKEY.value()) {
1211 mStkContext[slotId].mIsInputPending = true;
1212 } else if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1213 AppInterface.CommandType.SET_UP_MENU.value() ||
1214 mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1215 AppInterface.CommandType.SELECT_ITEM.value()) {
1216 mStkContext[slotId].mIsMenuPending = true;
1217 } else {
1218 }
1219 CatLog.d(LOG_TAG, "finish pending activity.");
1220 activity.finish();
1221 mStkContext[slotId].mActivityInstance = null;
1222 }
1223 if (dialog != null) {
1224 CatLog.d(LOG_TAG, "finish pending dialog.");
1225 mStkContext[slotId].mIsDialogPending = true;
1226 dialog.finish();
1227 mStkContext[slotId].mDialogInstance = null;
1228 }
1229 }
1230 /**
1231 * This method is used for restoring pending instances from stack.
1232 */
1233 private void restoreInstanceFromStackBySlot(int slotId) {
1234 AppInterface.CommandType cmdType = mStkContext[slotId].mCurrentCmd.getCmdType();
1235
1236 CatLog.d(LOG_TAG, "restoreInstanceFromStackBySlot cmdType : " + cmdType);
1237 switch(cmdType) {
1238 case GET_INPUT:
1239 case GET_INKEY:
1240 launchInputActivity(slotId);
1241 //Set mMenuIsVisible to true for showing main menu for
1242 //following session end command.
1243 mStkContext[slotId].mMenuIsVisible = true;
1244 break;
1245 case DISPLAY_TEXT:
1246 launchTextDialog(slotId);
1247 break;
1248 case LAUNCH_BROWSER:
1249 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.geTextMessage(),
1250 slotId);
1251 break;
1252 case OPEN_CHANNEL:
1253 launchOpenChannelDialog(slotId);
1254 break;
1255 case SET_UP_CALL:
1256 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.getCallSettings().
1257 confirmMsg, slotId);
1258 break;
1259 case SET_UP_MENU:
1260 case SELECT_ITEM:
1261 launchMenuActivity(null, slotId);
1262 break;
1263 default:
1264 break;
1265 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001266 }
1267
Wink Savillee68857d2014-10-17 15:23:05 -07001268 private void launchMenuActivity(Menu menu, int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001269 Intent newIntent = new Intent(Intent.ACTION_VIEW);
Wink Savillee68857d2014-10-17 15:23:05 -07001270 String targetActivity = STK_MENU_ACTIVITY_NAME;
1271 String uriString = STK_MENU_URI + System.currentTimeMillis();
1272 //Set unique URI to create a new instance of activity for different slotId.
1273 Uri uriData = Uri.parse(uriString);
1274
1275 CatLog.d(LOG_TAG, "launchMenuActivity, slotId: " + slotId + " , " +
1276 uriData.toString() + " , " + mStkContext[slotId].mOpCode + ", "
1277 + mStkContext[slotId].mMenuState);
1278 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1279 int intentFlags = Intent.FLAG_ACTIVITY_NEW_TASK;
1280
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001281 if (menu == null) {
1282 // We assume this was initiated by the user pressing the tool kit icon
Wink Savillee68857d2014-10-17 15:23:05 -07001283 intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.yes, slotId);
1284 if (mStkContext[slotId].mOpCode == OP_END_SESSION) {
1285 CatLog.d(LOG_TAG, "launchMenuActivity, return OP_END_SESSION");
1286 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
1287 if (mStkContext[slotId].mMainActivityInstance != null) {
1288 CatLog.d(LOG_TAG, "launchMenuActivity, mMainActivityInstance is not null");
1289 return;
1290 }
Wink Savillee68857d2014-10-17 15:23:05 -07001291 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001292
Wink Savillee68857d2014-10-17 15:23:05 -07001293 //If the last pending menu is secondary menu, "STATE" should be "STATE_SECONDARY".
1294 //Otherwise, it should be "STATE_MAIN".
1295 if (mStkContext[slotId].mOpCode == OP_LAUNCH_APP &&
1296 mStkContext[slotId].mMenuState == StkMenuActivity.STATE_SECONDARY) {
1297 newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
1298 } else {
1299 newIntent.putExtra("STATE", StkMenuActivity.STATE_MAIN);
1300 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
1301 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001302 } else {
1303 // We don't know and we'll let getFlagActivityNoUserAction decide.
Wink Savillee68857d2014-10-17 15:23:05 -07001304 intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001305 newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
Wink Savillee68857d2014-10-17 15:23:05 -07001306 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_SECONDARY;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001307 }
Wink Savillee68857d2014-10-17 15:23:05 -07001308 newIntent.putExtra(SLOT_ID, slotId);
1309 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001310 newIntent.setFlags(intentFlags);
1311 mContext.startActivity(newIntent);
1312 }
1313
Wink Savillee68857d2014-10-17 15:23:05 -07001314 private void launchInputActivity(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001315 Intent newIntent = new Intent(Intent.ACTION_VIEW);
Wink Savillee68857d2014-10-17 15:23:05 -07001316 String targetActivity = STK_INPUT_ACTIVITY_NAME;
1317 String uriString = STK_INPUT_URI + System.currentTimeMillis();
1318 //Set unique URI to create a new instance of activity for different slotId.
1319 Uri uriData = Uri.parse(uriString);
1320
1321 CatLog.d(LOG_TAG, "launchInputActivity, slotId: " + slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001322 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
Wink Savillee68857d2014-10-17 15:23:05 -07001323 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1324 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1325 newIntent.putExtra("INPUT", mStkContext[slotId].mCurrentCmd.geInput());
1326 newIntent.putExtra(SLOT_ID, slotId);
1327 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001328 mContext.startActivity(newIntent);
1329 }
1330
Wink Savillee68857d2014-10-17 15:23:05 -07001331 private void launchTextDialog(int slotId) {
1332 CatLog.d(LOG_TAG, "launchTextDialog, slotId: " + slotId);
1333 Intent newIntent = new Intent();
1334 String targetActivity = STK_DIALOG_ACTIVITY_NAME;
1335 int action = getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
1336 String uriString = STK_DIALOG_URI + System.currentTimeMillis();
1337 //Set unique URI to create a new instance of activity for different slotId.
1338 Uri uriData = Uri.parse(uriString);
1339 if (newIntent != null) {
1340 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1341 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1342 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
1343 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1344 newIntent.setData(uriData);
1345 newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
1346 newIntent.putExtra(SLOT_ID, slotId);
1347 startActivity(newIntent);
Preeti Ahuja414bc412013-06-25 19:31:49 -07001348 // For display texts with immediate response, send the terminal response
1349 // immediately. responseNeeded will be false, if display text command has
1350 // the immediate response tlv.
1351 if (!mStkContext[slotId].mCurrentCmd.geTextMessage().responseNeeded) {
1352 sendResponse(RES_ID_CONFIRM, slotId, true);
1353 }
Wink Savillee68857d2014-10-17 15:23:05 -07001354 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001355 }
1356
Wink Savillee68857d2014-10-17 15:23:05 -07001357 public boolean isStkDialogActivated(Context context) {
1358 String stkDialogActivity = "com.android.stk.StkDialogActivity";
1359 boolean activated = false;
1360 final ActivityManager am = (ActivityManager) context.getSystemService(
1361 Context.ACTIVITY_SERVICE);
1362 String topActivity = am.getRunningTasks(1).get(0).topActivity.getClassName();
1363
1364 CatLog.d(LOG_TAG, "isStkDialogActivated: " + topActivity);
1365 if (topActivity.equals(stkDialogActivity)) {
1366 activated = true;
1367 }
1368 CatLog.d(LOG_TAG, "activated : " + activated);
1369 return activated;
Johan Hellman3aec01c2011-02-10 10:15:28 +01001370 }
1371
Preeti Ahuja95919342013-10-01 18:18:55 -07001372 private void sendSetUpEventResponse(int event, byte[] addedInfo, int slotId) {
Preeti Ahuja414bc412013-06-25 19:31:49 -07001373 CatLog.d(this, "sendSetUpEventResponse: event : " + event + "slotId = " + slotId);
Preeti Ahuja95919342013-10-01 18:18:55 -07001374
1375 if (mStkContext[slotId].mCurrentSetupEventCmd == null){
1376 CatLog.e(this, "mCurrentSetupEventCmd is null");
1377 return;
1378 }
1379
1380 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentSetupEventCmd);
1381
1382 resMsg.setResultCode(ResultCode.OK);
1383 resMsg.setEventDownload(event, addedInfo);
1384
1385 mStkService[slotId].onCmdResponse(resMsg);
1386 }
1387
1388 private void checkForSetupEvent(int event, Bundle args, int slotId) {
1389 boolean eventPresent = false;
1390 byte[] addedInfo = null;
1391 CatLog.d(this, "Event :" + event);
1392
1393 if (mStkContext[slotId].mSetupEventListSettings != null) {
1394 /* Checks if the event is present in the EventList updated by last
1395 * SetupEventList Proactive Command */
1396 for (int i : mStkContext[slotId].mSetupEventListSettings.eventList) {
1397 if (event == i) {
1398 eventPresent = true;
1399 break;
1400 }
1401 }
1402
1403 /* If Event is present send the response to ICC */
1404 if (eventPresent == true) {
1405 CatLog.d(this, " Event " + event + "exists in the EventList");
1406
1407 switch (event) {
Preeti Ahuja560be362014-11-25 19:38:24 -08001408 case IDLE_SCREEN_AVAILABLE_EVENT:
1409 sendSetUpEventResponse(event, addedInfo, slotId);
1410 removeSetUpEvent(event, slotId);
1411 break;
Preeti Ahuja95919342013-10-01 18:18:55 -07001412 case LANGUAGE_SELECTION_EVENT:
1413 String language = mContext
1414 .getResources().getConfiguration().locale.getLanguage();
1415 CatLog.d(this, "language: " + language);
1416 // Each language code is a pair of alpha-numeric characters.
1417 // Each alpha-numeric character shall be coded on one byte
1418 // using the SMS default 7-bit coded alphabet
1419 addedInfo = GsmAlphabet.stringToGsm8BitPacked(language);
1420 sendSetUpEventResponse(event, addedInfo, slotId);
1421 break;
1422 default:
1423 break;
1424 }
1425 } else {
1426 CatLog.e(this, " Event does not exist in the EventList");
1427 }
1428 } else {
1429 CatLog.e(this, "SetupEventList is not received. Ignoring the event: " + event);
1430 }
1431 }
1432
1433 private void removeSetUpEvent(int event, int slotId) {
1434 CatLog.d(this, "Remove Event :" + event);
1435
1436 if (mStkContext[slotId].mSetupEventListSettings != null) {
1437 /*
1438 * Make new Eventlist without the event
1439 */
1440 for (int i = 0; i < mStkContext[slotId].mSetupEventListSettings.eventList.length; i++) {
1441 if (event == mStkContext[slotId].mSetupEventListSettings.eventList[i]) {
1442 mStkContext[slotId].mSetupEventListSettings.eventList[i] = INVALID_SETUP_EVENT;
1443 break;
1444 }
1445 }
1446 }
1447 }
1448
1449 private void launchEventMessage(int slotId) {
1450 launchEventMessage(slotId, mStkContext[slotId].mCurrentCmd.geTextMessage());
1451 }
1452
Wink Savillee68857d2014-10-17 15:23:05 -07001453 private void launchEventMessage(int slotId, TextMessage msg) {
1454 if (msg == null || (msg.text != null && msg.text.length() == 0)) {
1455 CatLog.d(LOG_TAG, "launchEventMessage return");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001456 return;
1457 }
Wink Savillee68857d2014-10-17 15:23:05 -07001458
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001459 Toast toast = new Toast(mContext.getApplicationContext());
1460 LayoutInflater inflate = (LayoutInflater) mContext
1461 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
1462 View v = inflate.inflate(R.layout.stk_event_msg, null);
1463 TextView tv = (TextView) v
1464 .findViewById(com.android.internal.R.id.message);
1465 ImageView iv = (ImageView) v
1466 .findViewById(com.android.internal.R.id.icon);
1467 if (msg.icon != null) {
1468 iv.setImageBitmap(msg.icon);
1469 } else {
1470 iv.setVisibility(View.GONE);
1471 }
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301472 /* In case of 'self explanatory' stkapp should display the specified
1473 * icon in proactive command (but not the alpha string).
1474 * If icon is non-self explanatory and if the icon could not be displayed
1475 * then alpha string or text data should be displayed
1476 * Ref: ETSI 102.223,section 6.5.4
1477 */
1478 if (mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ||
1479 msg.icon == null || !msg.iconSelfExplanatory) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001480 tv.setText(msg.text);
1481 }
1482
1483 toast.setView(v);
1484 toast.setDuration(Toast.LENGTH_LONG);
1485 toast.setGravity(Gravity.BOTTOM, 0, 0);
1486 toast.show();
1487 }
1488
Wink Savillee68857d2014-10-17 15:23:05 -07001489 private void launchConfirmationDialog(TextMessage msg, int slotId) {
1490 msg.title = mStkContext[slotId].lastSelectedItem;
1491 Intent newIntent = new Intent();
1492 String targetActivity = STK_DIALOG_ACTIVITY_NAME;
1493 String uriString = STK_DIALOG_URI + System.currentTimeMillis();
1494 //Set unique URI to create a new instance of activity for different slotId.
1495 Uri uriData = Uri.parse(uriString);
1496
1497 if (newIntent != null) {
1498 newIntent.setClassName(this, targetActivity);
1499 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1500 | Intent.FLAG_ACTIVITY_NO_HISTORY
1501 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
1502 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1503 newIntent.putExtra("TEXT", msg);
1504 newIntent.putExtra(SLOT_ID, slotId);
1505 newIntent.setData(uriData);
1506 startActivity(newIntent);
1507 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001508 }
1509
1510 private void launchBrowser(BrowserSettings settings) {
1511 if (settings == null) {
1512 return;
1513 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001514
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001515 Uri data = null;
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07001516 String url;
1517 if (settings.url == null) {
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001518 // if the command did not contain a URL,
1519 // launch the browser to the default homepage.
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07001520 CatLog.d(this, "no url data provided by proactive command." +
1521 " launching browser with stk default URL ... ");
1522 url = SystemProperties.get(STK_BROWSER_DEFAULT_URL_SYSPROP,
1523 "http://www.google.com");
1524 } else {
1525 CatLog.d(this, "launch browser command has attached url = " + settings.url);
1526 url = settings.url;
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001527 }
David Brown7c03cfe2011-10-20 15:36:12 -07001528
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07001529 if (url.startsWith("http://") || url.startsWith("https://")) {
1530 data = Uri.parse(url);
1531 CatLog.d(this, "launching browser with url = " + url);
1532 } else {
1533 String modifiedUrl = "http://" + url;
1534 data = Uri.parse(modifiedUrl);
1535 CatLog.d(this, "launching browser with modified url = " + modifiedUrl);
1536 }
1537
1538 Intent intent = new Intent(Intent.ACTION_VIEW);
1539 intent.setData(data);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001540 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1541 switch (settings.mode) {
1542 case USE_EXISTING_BROWSER:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001543 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1544 break;
1545 case LAUNCH_NEW_BROWSER:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001546 intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
1547 break;
1548 case LAUNCH_IF_NOT_ALREADY_LAUNCHED:
1549 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1550 break;
1551 }
1552 // start browser activity
1553 startActivity(intent);
1554 // a small delay, let the browser start, before processing the next command.
Wink Saville79085fc2009-06-09 10:27:23 -07001555 // this is good for scenarios where a related DISPLAY TEXT command is
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001556 // followed immediately.
1557 try {
Ryuto Sawada350aaa62016-06-13 14:47:22 +09001558 Thread.sleep(3000);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001559 } catch (InterruptedException e) {}
1560 }
1561
Wink Savillee68857d2014-10-17 15:23:05 -07001562 private void launchIdleText(int slotId) {
Preeti Ahuja560be362014-11-25 19:38:24 -08001563 TextMessage msg = mStkContext[slotId].mIdleModeTextCmd.geTextMessage();
dujin.cha2a0eb2a2011-11-11 15:03:57 +09001564
Preeti Ahuja95919342013-10-01 18:18:55 -07001565 if (msg == null || msg.text ==null) {
1566 CatLog.d(LOG_TAG, msg == null ? "mCurrent.getTextMessage is NULL"
1567 : "mCurrent.getTextMessage.text is NULL");
Wink Savillee68857d2014-10-17 15:23:05 -07001568 mNotificationManager.cancel(getNotificationId(slotId));
Wink Saville046db4b2011-11-01 20:42:54 -07001569 return;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001570 } else {
Preeti Ahuja95919342013-10-01 18:18:55 -07001571 CatLog.d(LOG_TAG, "launchIdleText - text[" + msg.text
1572 + "] iconSelfExplanatory[" + msg.iconSelfExplanatory
1573 + "] icon[" + msg.icon + "], sim id: " + slotId);
Wink Savillee68857d2014-10-17 15:23:05 -07001574 CatLog.d(LOG_TAG, "Add IdleMode text");
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001575 PendingIntent pendingIntent = PendingIntent.getService(mContext, 0,
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001576 new Intent(mContext, StkAppService.class), 0);
fionaxu805eb572017-05-02 10:57:30 -07001577 createAllChannels();
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001578 final Notification.Builder notificationBuilder = new Notification.Builder(
fionaxu2c91c752017-04-21 18:11:57 -07001579 StkAppService.this, STK_NOTIFICATION_CHANNEL_ID);
Wink Savillee68857d2014-10-17 15:23:05 -07001580 if (mStkContext[slotId].mMainCmd != null &&
1581 mStkContext[slotId].mMainCmd.getMenu() != null) {
1582 notificationBuilder.setContentTitle(mStkContext[slotId].mMainCmd.getMenu().title);
Christopher Posselwhite2ad2ab72013-05-27 07:51:06 +02001583 } else {
1584 notificationBuilder.setContentTitle("");
1585 }
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001586 notificationBuilder
1587 .setSmallIcon(com.android.internal.R.drawable.stat_notify_sim_toolkit);
1588 notificationBuilder.setContentIntent(pendingIntent);
1589 notificationBuilder.setOngoing(true);
1590 // Set text and icon for the status bar and notification body.
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301591 if (mStkContext[slotId].mIdleModeTextCmd.hasIconLoadFailed() ||
1592 !msg.iconSelfExplanatory) {
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001593 notificationBuilder.setContentText(msg.text);
Christopher Posselwhite2ad2ab72013-05-27 07:51:06 +02001594 notificationBuilder.setTicker(msg.text);
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001595 }
1596 if (msg.icon != null) {
1597 notificationBuilder.setLargeIcon(msg.icon);
1598 } else {
1599 Bitmap bitmapIcon = BitmapFactory.decodeResource(StkAppService.this
1600 .getResources().getSystem(),
1601 com.android.internal.R.drawable.stat_notify_sim_toolkit);
1602 notificationBuilder.setLargeIcon(bitmapIcon);
1603 }
Selim Cinek62eb3fe2014-08-27 17:52:23 +02001604 notificationBuilder.setColor(mContext.getResources().getColor(
1605 com.android.internal.R.color.system_notification_accent_color));
Wink Savillee68857d2014-10-17 15:23:05 -07001606 mNotificationManager.notify(getNotificationId(slotId), notificationBuilder.build());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001607 }
1608 }
1609
fionaxu805eb572017-05-02 10:57:30 -07001610 /** Creates the notification channel and registers it with NotificationManager.
1611 * If a channel with the same ID is already registered, NotificationManager will
1612 * ignore this call.
1613 */
1614 private void createAllChannels() {
1615 mNotificationManager.createNotificationChannel(new NotificationChannel(
1616 STK_NOTIFICATION_CHANNEL_ID,
1617 getResources().getString(R.string.stk_channel_name),
1618 NotificationManager.IMPORTANCE_MIN));
1619 }
1620
Wink Savillee68857d2014-10-17 15:23:05 -07001621 private void launchToneDialog(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001622 Intent newIntent = new Intent(this, ToneDialog.class);
Wink Savillee68857d2014-10-17 15:23:05 -07001623 String uriString = STK_TONE_URI + slotId;
1624 Uri uriData = Uri.parse(uriString);
1625 //Set unique URI to create a new instance of activity for different slotId.
1626 CatLog.d(LOG_TAG, "launchToneDialog, slotId: " + slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001627 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1628 | Intent.FLAG_ACTIVITY_NO_HISTORY
1629 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
Wink Savillee68857d2014-10-17 15:23:05 -07001630 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1631 newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
1632 newIntent.putExtra("TONE", mStkContext[slotId].mCurrentCmd.getToneSettings());
1633 newIntent.putExtra(SLOT_ID, slotId);
1634 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001635 startActivity(newIntent);
1636 }
1637
Takanori Nakano49b12722016-02-16 14:34:14 +09001638 private void launchOpenChannelDialog(final int slotId) {
Wink Savillee68857d2014-10-17 15:23:05 -07001639 TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001640 if (msg == null) {
Wink Savillee68857d2014-10-17 15:23:05 -07001641 CatLog.d(LOG_TAG, "msg is null, return here");
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001642 return;
1643 }
1644
1645 msg.title = getResources().getString(R.string.stk_dialog_title);
1646 if (msg.text == null) {
1647 msg.text = getResources().getString(R.string.default_open_channel_msg);
1648 }
1649
1650 final AlertDialog dialog = new AlertDialog.Builder(mContext)
1651 .setIconAttribute(android.R.attr.alertDialogIcon)
1652 .setTitle(msg.title)
1653 .setMessage(msg.text)
1654 .setCancelable(false)
1655 .setPositiveButton(getResources().getString(R.string.stk_dialog_accept),
1656 new DialogInterface.OnClickListener() {
1657 public void onClick(DialogInterface dialog, int which) {
1658 Bundle args = new Bundle();
1659 args.putInt(RES_ID, RES_ID_CHOICE);
1660 args.putInt(CHOICE, YES);
1661 Message message = mServiceHandler.obtainMessage();
1662 message.arg1 = OP_RESPONSE;
Takanori Nakano49b12722016-02-16 14:34:14 +09001663 message.arg2 = slotId;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001664 message.obj = args;
1665 mServiceHandler.sendMessage(message);
1666 }
1667 })
1668 .setNegativeButton(getResources().getString(R.string.stk_dialog_reject),
1669 new DialogInterface.OnClickListener() {
1670 public void onClick(DialogInterface dialog, int which) {
1671 Bundle args = new Bundle();
1672 args.putInt(RES_ID, RES_ID_CHOICE);
1673 args.putInt(CHOICE, NO);
1674 Message message = mServiceHandler.obtainMessage();
1675 message.arg1 = OP_RESPONSE;
Takanori Nakano49b12722016-02-16 14:34:14 +09001676 message.arg2 = slotId;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001677 message.obj = args;
1678 mServiceHandler.sendMessage(message);
1679 }
1680 })
1681 .create();
1682
1683 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1684 if (!mContext.getResources().getBoolean(
1685 com.android.internal.R.bool.config_sf_slowBlur)) {
1686 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
1687 }
1688
1689 dialog.show();
1690 }
1691
Wink Savillee68857d2014-10-17 15:23:05 -07001692 private void launchTransientEventMessage(int slotId) {
1693 TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001694 if (msg == null) {
Wink Savillee68857d2014-10-17 15:23:05 -07001695 CatLog.d(LOG_TAG, "msg is null, return here");
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001696 return;
1697 }
1698
1699 msg.title = getResources().getString(R.string.stk_dialog_title);
1700
1701 final AlertDialog dialog = new AlertDialog.Builder(mContext)
1702 .setIconAttribute(android.R.attr.alertDialogIcon)
1703 .setTitle(msg.title)
1704 .setMessage(msg.text)
1705 .setCancelable(false)
1706 .setPositiveButton(getResources().getString(android.R.string.ok),
1707 new DialogInterface.OnClickListener() {
1708 public void onClick(DialogInterface dialog, int which) {
1709 }
1710 })
1711 .create();
1712
1713 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1714 if (!mContext.getResources().getBoolean(
1715 com.android.internal.R.bool.config_sf_slowBlur)) {
1716 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
1717 }
1718
1719 dialog.show();
1720 }
1721
Wink Savillee68857d2014-10-17 15:23:05 -07001722 private int getNotificationId(int slotId) {
1723 int notifyId = STK_NOTIFICATION_ID;
1724 if (slotId >= 0 && slotId < mSimCount) {
1725 notifyId += slotId;
1726 } else {
1727 CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
1728 }
1729 CatLog.d(LOG_TAG, "getNotificationId, slotId: " + slotId + ", notifyId: " + notifyId);
1730 return notifyId;
1731 }
1732
1733 private String getItemName(int itemId, int slotId) {
1734 Menu menu = mStkContext[slotId].mCurrentCmd.getMenu();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001735 if (menu == null) {
1736 return null;
1737 }
1738 for (Item item : menu.items) {
1739 if (item.id == itemId) {
1740 return item.text;
1741 }
1742 }
1743 return null;
1744 }
1745
Wink Savillee68857d2014-10-17 15:23:05 -07001746 private boolean removeMenu(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001747 try {
Wink Savillee68857d2014-10-17 15:23:05 -07001748 if (mStkContext[slotId].mCurrentMenu.items.size() == 1 &&
1749 mStkContext[slotId].mCurrentMenu.items.get(0) == null) {
1750 mStkContext[slotId].mSetupMenuState = STATE_NOT_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001751 return true;
1752 }
1753 } catch (NullPointerException e) {
Wink Savillee68857d2014-10-17 15:23:05 -07001754 CatLog.d(LOG_TAG, "Unable to get Menu's items size");
1755 mStkContext[slotId].mSetupMenuState = STATE_NOT_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001756 return true;
1757 }
Wink Savillee68857d2014-10-17 15:23:05 -07001758 mStkContext[slotId].mSetupMenuState = STATE_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001759 return false;
1760 }
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +05301761
Wink Savillee68857d2014-10-17 15:23:05 -07001762 StkContext getStkContext(int slotId) {
1763 if (slotId >= 0 && slotId < mSimCount) {
1764 return mStkContext[slotId];
1765 } else {
1766 CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
1767 return null;
1768 }
1769 }
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +05301770
1771 private void handleAlphaNotify(Bundle args) {
1772 String alphaString = args.getString(AppInterface.ALPHA_STRING);
1773
1774 CatLog.d(this, "Alpha string received from card: " + alphaString);
1775 Toast toast = Toast.makeText(sInstance, alphaString, Toast.LENGTH_LONG);
1776 toast.setGravity(Gravity.TOP, 0, 0);
1777 toast.show();
1778 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001779}