blob: dc551a6542e7ba0fb4d189eeb1fe7243930b0c2a [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;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +090028import android.app.ActivityManagerNative;
29import android.app.IProcessObserver;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080030import android.content.Context;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -050031import android.content.DialogInterface;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080032import android.content.Intent;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +090033import android.content.pm.PackageManager;
34import android.content.pm.ResolveInfo;
Preeti Ahuja95919342013-10-01 18:18:55 -070035import android.content.res.Configuration;
Srikanth Chintala89aa6602014-03-14 16:26:57 +053036import android.content.res.Resources;
37import android.content.res.Resources.NotFoundException;
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +010038import android.graphics.Bitmap;
39import android.graphics.BitmapFactory;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080040import android.net.Uri;
41import android.os.Bundle;
42import android.os.Handler;
43import android.os.IBinder;
44import android.os.Looper;
45import android.os.Message;
Takanori Nakanoc8054ba2016-08-15 19:18:16 +090046import android.os.Parcel;
Sooraj Sasindrana4160472016-10-12 16:28:25 -070047import android.os.PersistableBundle;
Preeti Ahuja560be362014-11-25 19:38:24 -080048import android.os.PowerManager;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +090049import android.os.RemoteException;
Preeti Ahujaa7cdca22013-10-01 18:20:56 -070050import android.os.SystemProperties;
Srikanth Chintala89aa6602014-03-14 16:26:57 +053051import android.os.Vibrator;
Preeti Ahuja95919342013-10-01 18:18:55 -070052import android.provider.Settings;
Takanori Nakano3776e2c2016-10-14 16:54:28 +090053import android.support.v4.content.LocalBroadcastManager;
Sooraj Sasindrana4160472016-10-12 16:28:25 -070054import android.telephony.CarrierConfigManager;
Wink Saville56469d52009-04-02 01:37:03 -070055import android.telephony.TelephonyManager;
Preeti Ahujaa7cdca22013-10-01 18:20:56 -070056import android.text.TextUtils;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080057import android.view.Gravity;
58import android.view.LayoutInflater;
59import android.view.View;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -050060import android.view.WindowManager;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080061import android.widget.ImageView;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080062import android.widget.TextView;
63import android.widget.Toast;
Wink Savillee68857d2014-10-17 15:23:05 -070064import android.content.IntentFilter;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080065
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070066import com.android.internal.telephony.cat.AppInterface;
Preeti Ahuja95919342013-10-01 18:18:55 -070067import com.android.internal.telephony.cat.LaunchBrowserMode;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070068import com.android.internal.telephony.cat.Menu;
69import com.android.internal.telephony.cat.Item;
70import com.android.internal.telephony.cat.ResultCode;
71import com.android.internal.telephony.cat.CatCmdMessage;
72import com.android.internal.telephony.cat.CatCmdMessage.BrowserSettings;
Preeti Ahuja95919342013-10-01 18:18:55 -070073import com.android.internal.telephony.cat.CatCmdMessage.SetupEventListSettings;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070074import com.android.internal.telephony.cat.CatLog;
75import com.android.internal.telephony.cat.CatResponseMessage;
76import com.android.internal.telephony.cat.TextMessage;
Srikanth Chintala89aa6602014-03-14 16:26:57 +053077import com.android.internal.telephony.cat.ToneSettings;
Wink Saville94e982b2014-07-11 07:38:14 -070078import com.android.internal.telephony.uicc.IccRefreshResponse;
Wink Savillee68857d2014-10-17 15:23:05 -070079import com.android.internal.telephony.PhoneConstants;
Preeti Ahuja95919342013-10-01 18:18:55 -070080import com.android.internal.telephony.GsmAlphabet;
Legler Wuaeefef52014-10-27 00:57:18 +080081import com.android.internal.telephony.cat.CatService;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080082
Preeti Ahujaa7cdca22013-10-01 18:20:56 -070083import java.util.Iterator;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080084import java.util.LinkedList;
Wink Savillee68857d2014-10-17 15:23:05 -070085import java.lang.System;
86import java.util.List;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080087
Preeti Ahuja95919342013-10-01 18:18:55 -070088import static com.android.internal.telephony.cat.CatCmdMessage.
Preeti Ahuja560be362014-11-25 19:38:24 -080089 SetupEventListConstants.IDLE_SCREEN_AVAILABLE_EVENT;
90import static com.android.internal.telephony.cat.CatCmdMessage.
Preeti Ahuja95919342013-10-01 18:18:55 -070091 SetupEventListConstants.LANGUAGE_SELECTION_EVENT;
92
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080093/**
94 * SIM toolkit application level service. Interacts with Telephopny messages,
95 * application's launch and user input from STK UI elements.
Wink Saville79085fc2009-06-09 10:27:23 -070096 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080097 */
98public class StkAppService extends Service implements Runnable {
99
100 // members
Wink Savillee68857d2014-10-17 15:23:05 -0700101 protected class StkContext {
102 protected CatCmdMessage mMainCmd = null;
103 protected CatCmdMessage mCurrentCmd = null;
104 protected CatCmdMessage mCurrentMenuCmd = null;
105 protected Menu mCurrentMenu = null;
106 protected String lastSelectedItem = null;
107 protected boolean mMenuIsVisible = false;
108 protected boolean mIsInputPending = false;
109 protected boolean mIsMenuPending = false;
110 protected boolean mIsDialogPending = false;
111 protected boolean responseNeeded = true;
112 protected boolean launchBrowser = false;
113 protected BrowserSettings mBrowserSettings = null;
114 protected LinkedList<DelayedCmd> mCmdsQ = null;
115 protected boolean mCmdInProgress = false;
116 protected int mStkServiceState = STATE_UNKNOWN;
117 protected int mSetupMenuState = STATE_UNKNOWN;
118 protected int mMenuState = StkMenuActivity.STATE_INIT;
119 protected int mOpCode = -1;
120 private Activity mActivityInstance = null;
121 private Activity mDialogInstance = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700122 private int mSlotId = 0;
Preeti Ahuja95919342013-10-01 18:18:55 -0700123 private SetupEventListSettings mSetupEventListSettings = null;
124 private boolean mClearSelectItem = false;
125 private boolean mDisplayTextDlgIsVisibile = false;
126 private CatCmdMessage mCurrentSetupEventCmd = null;
Preeti Ahuja560be362014-11-25 19:38:24 -0800127 private CatCmdMessage mIdleModeTextCmd = null;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +0900128 private boolean mIdleModeTextVisible = false;
Wink Savillee68857d2014-10-17 15:23:05 -0700129 final synchronized void setPendingActivityInstance(Activity act) {
130 CatLog.d(this, "setPendingActivityInstance act : " + mSlotId + ", " + act);
131 callSetActivityInstMsg(OP_SET_ACT_INST, mSlotId, act);
132 }
133 final synchronized Activity getPendingActivityInstance() {
134 CatLog.d(this, "getPendingActivityInstance act : " + mSlotId + ", " +
135 mActivityInstance);
136 return mActivityInstance;
137 }
138 final synchronized void setPendingDialogInstance(Activity act) {
139 CatLog.d(this, "setPendingDialogInstance act : " + mSlotId + ", " + act);
140 callSetActivityInstMsg(OP_SET_DAL_INST, mSlotId, act);
141 }
142 final synchronized Activity getPendingDialogInstance() {
143 CatLog.d(this, "getPendingDialogInstance act : " + mSlotId + ", " +
144 mDialogInstance);
145 return mDialogInstance;
146 }
Wink Savillee68857d2014-10-17 15:23:05 -0700147 }
148
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800149 private volatile Looper mServiceLooper;
150 private volatile ServiceHandler mServiceHandler;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800151 private Context mContext = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800152 private NotificationManager mNotificationManager = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800153 static StkAppService sInstance = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700154 private AppInterface[] mStkService = null;
155 private StkContext[] mStkContext = null;
156 private int mSimCount = 0;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +0900157 private IProcessObserver.Stub mProcessObserver = null;
Srikanth Chintala89aa6602014-03-14 16:26:57 +0530158 private TonePlayer mTonePlayer = null;
159 private Vibrator mVibrator = null;
Preeti Ahuja95919342013-10-01 18:18:55 -0700160
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800161 // Used for setting FLAG_ACTIVITY_NO_USER_ACTION when
162 // creating an intent.
163 private enum InitiatedByUserAction {
164 yes, // The action was started via a user initiated action
165 unknown, // Not known for sure if user initated the action
166 }
167
168 // constants
169 static final String OPCODE = "op";
170 static final String CMD_MSG = "cmd message";
171 static final String RES_ID = "response id";
172 static final String MENU_SELECTION = "menu selection";
173 static final String INPUT = "input";
174 static final String HELP = "help";
175 static final String CONFIRMATION = "confirm";
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500176 static final String CHOICE = "choice";
Wink Savillee68857d2014-10-17 15:23:05 -0700177 static final String SLOT_ID = "SLOT_ID";
178 static final String STK_CMD = "STK CMD";
179 static final String STK_DIALOG_URI = "stk://com.android.stk/dialog/";
180 static final String STK_MENU_URI = "stk://com.android.stk/menu/";
181 static final String STK_INPUT_URI = "stk://com.android.stk/input/";
182 static final String STK_TONE_URI = "stk://com.android.stk/tone/";
Srikanth Chintala89aa6602014-03-14 16:26:57 +0530183 static final String FINISH_TONE_ACTIVITY_ACTION =
184 "android.intent.action.stk.finish_activity";
Preeti Ahuja95919342013-10-01 18:18:55 -0700185
186 // These below constants are used for SETUP_EVENT_LIST
187 static final String SETUP_EVENT_TYPE = "event";
188 static final String SETUP_EVENT_CAUSE = "cause";
189
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800190 // operations ids for different service functionality.
191 static final int OP_CMD = 1;
192 static final int OP_RESPONSE = 2;
193 static final int OP_LAUNCH_APP = 3;
194 static final int OP_END_SESSION = 4;
195 static final int OP_BOOT_COMPLETED = 5;
196 private static final int OP_DELAYED_MSG = 6;
Wink Saville94e982b2014-07-11 07:38:14 -0700197 static final int OP_CARD_STATUS_CHANGED = 7;
Wink Savillee68857d2014-10-17 15:23:05 -0700198 static final int OP_SET_ACT_INST = 8;
199 static final int OP_SET_DAL_INST = 9;
Ryuto Sawada08c821c2016-08-08 18:29:02 +0900200 static final int OP_LOCALE_CHANGED = 10;
201 static final int OP_ALPHA_NOTIFY = 11;
202 static final int OP_IDLE_SCREEN = 12;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800203
Preeti Ahuja95919342013-10-01 18:18:55 -0700204 //Invalid SetupEvent
205 static final int INVALID_SETUP_EVENT = 0xFF;
206
Srikanth Chintala89aa6602014-03-14 16:26:57 +0530207 // Message id to signal stop tone due to play tone timeout.
208 private static final int OP_STOP_TONE = 16;
209
210 // Message id to signal stop tone on user keyback.
211 static final int OP_STOP_TONE_USER = 17;
212
213 // Message id to remove stop tone message from queue.
214 private static final int STOP_TONE_WHAT = 100;
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;
Srikanth Chintalaba103002015-11-30 10:49:52 -0800227 static final int RES_ID_ERROR = 24;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800228
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500229 static final int YES = 1;
230 static final int NO = 0;
231
Wink Savillee68857d2014-10-17 15:23:05 -0700232 static final int STATE_UNKNOWN = -1;
233 static final int STATE_NOT_EXIST = 0;
234 static final int STATE_EXIST = 1;
Wink Saville79085fc2009-06-09 10:27:23 -0700235
Wink Savillee68857d2014-10-17 15:23:05 -0700236 private static final String PACKAGE_NAME = "com.android.stk";
237 private static final String STK_MENU_ACTIVITY_NAME = PACKAGE_NAME + ".StkMenuActivity";
238 private static final String STK_INPUT_ACTIVITY_NAME = PACKAGE_NAME + ".StkInputActivity";
239 private static final String STK_DIALOG_ACTIVITY_NAME = PACKAGE_NAME + ".StkDialogActivity";
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800240 // Notification id used to display Idle Mode text in NotificationManager.
241 private static final int STK_NOTIFICATION_ID = 333;
fionaxu2c91c752017-04-21 18:11:57 -0700242 // Notification channel containing all mobile service messages notifications.
243 private static final String STK_NOTIFICATION_CHANNEL_ID = "mobileServiceMessages";
244
Wink Savillee68857d2014-10-17 15:23:05 -0700245 private static final String LOG_TAG = new Object(){}.getClass().getEnclosingClass().getName();
Wink Saville79085fc2009-06-09 10:27:23 -0700246
Takanori Nakano3776e2c2016-10-14 16:54:28 +0900247 static final String SESSION_ENDED = "session_ended";
248
Wink Saville79085fc2009-06-09 10:27:23 -0700249 // Inner class used for queuing telephony messages (proactive commands,
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800250 // session end) while the service is busy processing a previous message.
251 private class DelayedCmd {
252 // members
253 int id;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700254 CatCmdMessage msg;
Wink Savillee68857d2014-10-17 15:23:05 -0700255 int slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800256
Wink Savillee68857d2014-10-17 15:23:05 -0700257 DelayedCmd(int id, CatCmdMessage msg, int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800258 this.id = id;
259 this.msg = msg;
Wink Savillee68857d2014-10-17 15:23:05 -0700260 this.slotId = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800261 }
262 }
263
Preeti Ahujaa7cdca22013-10-01 18:20:56 -0700264 // system property to set the STK specific default url for launch browser proactive cmds
265 private static final String STK_BROWSER_DEFAULT_URL_SYSPROP = "persist.radio.stk.default_url";
266
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800267 @Override
268 public void onCreate() {
Wink Savillee68857d2014-10-17 15:23:05 -0700269 CatLog.d(LOG_TAG, "onCreate()+");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800270 // Initialize members
Wink Savillee68857d2014-10-17 15:23:05 -0700271 int i = 0;
272 mContext = getBaseContext();
273 mSimCount = TelephonyManager.from(mContext).getSimCount();
274 CatLog.d(LOG_TAG, "simCount: " + mSimCount);
275 mStkService = new AppInterface[mSimCount];
276 mStkContext = new StkContext[mSimCount];
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +0900277
Wink Savillee68857d2014-10-17 15:23:05 -0700278 for (i = 0; i < mSimCount; i++) {
279 CatLog.d(LOG_TAG, "slotId: " + i);
Legler Wuaeefef52014-10-27 00:57:18 +0800280 mStkService[i] = CatService.getInstance(i);
Wink Savillee68857d2014-10-17 15:23:05 -0700281 mStkContext[i] = new StkContext();
282 mStkContext[i].mSlotId = i;
283 mStkContext[i].mCmdsQ = new LinkedList<DelayedCmd>();
284 }
285
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800286 Thread serviceThread = new Thread(null, this, "Stk App Service");
287 serviceThread.start();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800288 mNotificationManager = (NotificationManager) mContext
289 .getSystemService(Context.NOTIFICATION_SERVICE);
290 sInstance = this;
291 }
292
293 @Override
294 public void onStart(Intent intent, int startId) {
Wink Savillee68857d2014-10-17 15:23:05 -0700295 if (intent == null) {
296 CatLog.d(LOG_TAG, "StkAppService onStart intent is null so return");
Banavathu, Srinivas Naik87cda962012-07-17 15:32:44 +0530297 return;
298 }
299
Wink Savillee68857d2014-10-17 15:23:05 -0700300 Bundle args = intent.getExtras();
301 if (args == null) {
302 CatLog.d(LOG_TAG, "StkAppService onStart args is null so return");
303 return;
304 }
305
306 int op = args.getInt(OPCODE);
307 int slotId = 0;
308 int i = 0;
309 if (op != OP_BOOT_COMPLETED) {
310 slotId = args.getInt(SLOT_ID);
311 }
Cuihtlauac ALVARADObde7f032015-05-29 16:25:12 +0200312 CatLog.d(LOG_TAG, "onStart sim id: " + slotId + ", op: " + op + ", *****");
Wink Savillee68857d2014-10-17 15:23:05 -0700313 if ((slotId >= 0 && slotId < mSimCount) && mStkService[slotId] == null) {
Legler Wuaeefef52014-10-27 00:57:18 +0800314 mStkService[slotId] = CatService.getInstance(slotId);
Wink Savillee68857d2014-10-17 15:23:05 -0700315 if (mStkService[slotId] == null) {
316 CatLog.d(LOG_TAG, "mStkService is: " + mStkContext[slotId].mStkServiceState);
317 mStkContext[slotId].mStkServiceState = STATE_NOT_EXIST;
318 //Check other StkService state.
319 //If all StkServices are not available, stop itself and uninstall apk.
320 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
321 if (i != slotId
Tsukasa Goto029332b2016-10-05 17:12:06 +0900322 && (mStkService[i] != null)
Wink Savillee68857d2014-10-17 15:23:05 -0700323 && (mStkContext[i].mStkServiceState == STATE_UNKNOWN
324 || mStkContext[i].mStkServiceState == STATE_EXIST)) {
325 break;
326 }
327 }
328 } else {
329 mStkContext[slotId].mStkServiceState = STATE_EXIST;
330 }
331 if (i == mSimCount) {
332 stopSelf();
333 StkAppInstaller.unInstall(mContext);
334 return;
335 }
336 }
337
Banavathu, Srinivas Naik87cda962012-07-17 15:32:44 +0530338 waitForLooper();
John Wang62acae42009-10-08 11:20:23 -0700339
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800340 Message msg = mServiceHandler.obtainMessage();
Wink Savillee68857d2014-10-17 15:23:05 -0700341 msg.arg1 = op;
342 msg.arg2 = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800343 switch(msg.arg1) {
344 case OP_CMD:
345 msg.obj = args.getParcelable(CMD_MSG);
346 break;
347 case OP_RESPONSE:
Wink Saville94e982b2014-07-11 07:38:14 -0700348 case OP_CARD_STATUS_CHANGED:
Preeti Ahuja95919342013-10-01 18:18:55 -0700349 case OP_LOCALE_CHANGED:
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +0530350 case OP_ALPHA_NOTIFY:
Preeti Ahuja560be362014-11-25 19:38:24 -0800351 case OP_IDLE_SCREEN:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800352 msg.obj = args;
353 /* falls through */
354 case OP_LAUNCH_APP:
355 case OP_END_SESSION:
356 case OP_BOOT_COMPLETED:
357 break;
Srikanth Chintala89aa6602014-03-14 16:26:57 +0530358 case OP_STOP_TONE_USER:
359 msg.obj = args;
360 msg.what = STOP_TONE_WHAT;
361 break;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800362 default:
363 return;
364 }
365 mServiceHandler.sendMessage(msg);
366 }
367
368 @Override
369 public void onDestroy() {
Wink Savillee68857d2014-10-17 15:23:05 -0700370 CatLog.d(LOG_TAG, "onDestroy()");
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +0900371 unregisterProcessObserver();
Tsukasa Gotou54afbdd2016-01-07 16:30:20 +0900372 sInstance = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800373 waitForLooper();
374 mServiceLooper.quit();
375 }
376
377 @Override
378 public IBinder onBind(Intent intent) {
379 return null;
380 }
381
382 public void run() {
383 Looper.prepare();
384
385 mServiceLooper = Looper.myLooper();
386 mServiceHandler = new ServiceHandler();
387
388 Looper.loop();
389 }
390
391 /*
392 * Package api used by StkMenuActivity to indicate if its on the foreground.
393 */
Wink Savillee68857d2014-10-17 15:23:05 -0700394 void indicateMenuVisibility(boolean visibility, int slotId) {
395 if (slotId >= 0 && slotId < mSimCount) {
396 mStkContext[slotId].mMenuIsVisible = visibility;
397 }
398 }
399
Preeti Ahuja95919342013-10-01 18:18:55 -0700400 /*
401 * Package api used by StkDialogActivity to indicate if its on the foreground.
402 */
403 void setDisplayTextDlgVisibility(boolean visibility, int slotId) {
404 if (slotId >= 0 && slotId < mSimCount) {
405 mStkContext[slotId].mDisplayTextDlgIsVisibile = visibility;
406 }
407 }
408
Wink Savillee68857d2014-10-17 15:23:05 -0700409 boolean isInputPending(int slotId) {
410 if (slotId >= 0 && slotId < mSimCount) {
411 CatLog.d(LOG_TAG, "isInputFinishBySrv: " + mStkContext[slotId].mIsInputPending);
412 return mStkContext[slotId].mIsInputPending;
413 }
414 return false;
415 }
416
417 boolean isMenuPending(int slotId) {
418 if (slotId >= 0 && slotId < mSimCount) {
419 CatLog.d(LOG_TAG, "isMenuPending: " + mStkContext[slotId].mIsMenuPending);
420 return mStkContext[slotId].mIsMenuPending;
421 }
422 return false;
423 }
424
425 boolean isDialogPending(int slotId) {
426 if (slotId >= 0 && slotId < mSimCount) {
427 CatLog.d(LOG_TAG, "isDialogPending: " + mStkContext[slotId].mIsDialogPending);
428 return mStkContext[slotId].mIsDialogPending;
429 }
430 return false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800431 }
432
Takanori Nakano3776e2c2016-10-14 16:54:28 +0900433 boolean isMainMenuAvailable(int slotId) {
434 if (slotId >= 0 && slotId < mSimCount) {
435 // The main menu can handle the next user operation if the previous session finished.
436 return (mStkContext[slotId].lastSelectedItem == null) ? true : false;
437 }
438 return false;
439 }
440
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800441 /*
442 * Package api used by StkMenuActivity to get its Menu parameter.
443 */
Wink Savillee68857d2014-10-17 15:23:05 -0700444 Menu getMenu(int slotId) {
445 CatLog.d(LOG_TAG, "StkAppService, getMenu, sim id: " + slotId);
446 if (slotId >=0 && slotId < mSimCount) {
447 return mStkContext[slotId].mCurrentMenu;
448 } else {
449 return null;
450 }
451 }
452
453 /*
454 * Package api used by StkMenuActivity to get its Main Menu parameter.
455 */
456 Menu getMainMenu(int slotId) {
457 CatLog.d(LOG_TAG, "StkAppService, getMainMenu, sim id: " + slotId);
w30234a08cffe2015-02-04 15:13:25 -0800458 if (slotId >=0 && slotId < mSimCount && (mStkContext[slotId].mMainCmd != null)) {
Takanori Nakanoc8054ba2016-08-15 19:18:16 +0900459 Menu menu = mStkContext[slotId].mMainCmd.getMenu();
460 if (menu != null && mSimCount > PhoneConstants.MAX_PHONE_COUNT_SINGLE_SIM) {
461 // If alpha identifier or icon identifier with the self-explanatory qualifier is
462 // specified in SET-UP MENU command, it should be more prioritized than preset ones.
463 if (menu.title == null
464 && (menu.titleIcon == null || !menu.titleIconSelfExplanatory)) {
465 StkMenuConfig config = StkMenuConfig.getInstance(getApplicationContext());
466 String label = config.getLabel(slotId);
467 Bitmap icon = config.getIcon(slotId);
468 if (label != null || icon != null) {
469 Parcel parcel = Parcel.obtain();
470 menu.writeToParcel(parcel, 0);
471 parcel.setDataPosition(0);
472 menu = Menu.CREATOR.createFromParcel(parcel);
473 parcel.recycle();
474 menu.title = label;
475 menu.titleIcon = icon;
476 menu.titleIconSelfExplanatory = false;
477 }
478 }
479 }
480 return menu;
Wink Savillee68857d2014-10-17 15:23:05 -0700481 } else {
482 return null;
483 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800484 }
485
486 /*
487 * Package api used by UI Activities and Dialogs to communicate directly
488 * with the service to deliver state information and parameters.
489 */
490 static StkAppService getInstance() {
491 return sInstance;
492 }
493
494 private void waitForLooper() {
495 while (mServiceHandler == null) {
496 synchronized (this) {
497 try {
498 wait(100);
499 } catch (InterruptedException e) {
500 }
501 }
502 }
503 }
504
505 private final class ServiceHandler extends Handler {
506 @Override
507 public void handleMessage(Message msg) {
Wink Savillee68857d2014-10-17 15:23:05 -0700508 if(null == msg) {
509 CatLog.d(LOG_TAG, "ServiceHandler handleMessage msg is null");
510 return;
511 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800512 int opcode = msg.arg1;
Wink Savillee68857d2014-10-17 15:23:05 -0700513 int slotId = msg.arg2;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800514
Wink Savillee68857d2014-10-17 15:23:05 -0700515 CatLog.d(LOG_TAG, "handleMessage opcode[" + opcode + "], sim id[" + slotId + "]");
516 if (opcode == OP_CMD && msg.obj != null &&
517 ((CatCmdMessage)msg.obj).getCmdType()!= null) {
518 CatLog.d(LOG_TAG, "cmdName[" + ((CatCmdMessage)msg.obj).getCmdType().name() + "]");
519 }
520 mStkContext[slotId].mOpCode = opcode;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800521 switch (opcode) {
522 case OP_LAUNCH_APP:
Wink Savillee68857d2014-10-17 15:23:05 -0700523 if (mStkContext[slotId].mMainCmd == null) {
524 CatLog.d(LOG_TAG, "mMainCmd is null");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800525 // nothing todo when no SET UP MENU command didn't arrive.
526 return;
527 }
Wink Savillee68857d2014-10-17 15:23:05 -0700528 CatLog.d(LOG_TAG, "handleMessage OP_LAUNCH_APP - mCmdInProgress[" +
529 mStkContext[slotId].mCmdInProgress + "]");
530
531 //If there is a pending activity for the slot id,
532 //just finish it and create a new one to handle the pending command.
533 cleanUpInstanceStackBySlot(slotId);
534
Wink Savillee68857d2014-10-17 15:23:05 -0700535 CatLog.d(LOG_TAG, "Current cmd type: " +
536 mStkContext[slotId].mCurrentCmd.getCmdType());
537 //Restore the last command from stack by slot id.
538 restoreInstanceFromStackBySlot(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800539 break;
540 case OP_CMD:
Wink Savillee68857d2014-10-17 15:23:05 -0700541 CatLog.d(LOG_TAG, "[OP_CMD]");
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700542 CatCmdMessage cmdMsg = (CatCmdMessage) msg.obj;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800543 // There are two types of commands:
544 // 1. Interactive - user's response is required.
545 // 2. Informative - display a message, no interaction with the user.
546 //
Wink Saville79085fc2009-06-09 10:27:23 -0700547 // Informative commands can be handled immediately without any delay.
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800548 // Interactive commands can't override each other. So if a command
549 // is already in progress, we need to queue the next command until
550 // the user has responded or a timeout expired.
551 if (!isCmdInteractive(cmdMsg)) {
Wink Savillee68857d2014-10-17 15:23:05 -0700552 handleCmd(cmdMsg, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800553 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700554 if (!mStkContext[slotId].mCmdInProgress) {
555 mStkContext[slotId].mCmdInProgress = true;
556 handleCmd((CatCmdMessage) msg.obj, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800557 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700558 CatLog.d(LOG_TAG, "[Interactive][in progress]");
559 mStkContext[slotId].mCmdsQ.addLast(new DelayedCmd(OP_CMD,
560 (CatCmdMessage) msg.obj, slotId));
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800561 }
562 }
563 break;
564 case OP_RESPONSE:
Preeti Ahuja414bc412013-06-25 19:31:49 -0700565 handleCmdResponse((Bundle) msg.obj, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800566 // call delayed commands if needed.
Wink Savillee68857d2014-10-17 15:23:05 -0700567 if (mStkContext[slotId].mCmdsQ.size() != 0) {
568 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800569 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700570 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800571 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800572 break;
573 case OP_END_SESSION:
Wink Savillee68857d2014-10-17 15:23:05 -0700574 if (!mStkContext[slotId].mCmdInProgress) {
575 mStkContext[slotId].mCmdInProgress = true;
576 handleSessionEnd(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800577 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700578 mStkContext[slotId].mCmdsQ.addLast(
579 new DelayedCmd(OP_END_SESSION, null, slotId));
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800580 }
581 break;
582 case OP_BOOT_COMPLETED:
Wink Savillee68857d2014-10-17 15:23:05 -0700583 CatLog.d(LOG_TAG, " OP_BOOT_COMPLETED");
584 int i = 0;
585 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
586 if (mStkContext[i].mMainCmd != null) {
587 break;
588 }
589 }
590 if (i == mSimCount) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800591 StkAppInstaller.unInstall(mContext);
592 }
593 break;
594 case OP_DELAYED_MSG:
Wink Savillee68857d2014-10-17 15:23:05 -0700595 handleDelayedCmd(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800596 break;
Wink Saville94e982b2014-07-11 07:38:14 -0700597 case OP_CARD_STATUS_CHANGED:
Wink Savillee68857d2014-10-17 15:23:05 -0700598 CatLog.d(LOG_TAG, "Card/Icc Status change received");
599 handleCardStatusChangeAndIccRefresh((Bundle) msg.obj, slotId);
600 break;
601 case OP_SET_ACT_INST:
Yoshiaki Naka28d7a722017-10-24 17:32:16 +0900602 Activity act = (Activity) msg.obj;
603 if (mStkContext[slotId].mActivityInstance != act) {
604 CatLog.d(LOG_TAG, "Set activity instance - " + act);
605 Activity previous = mStkContext[slotId].mActivityInstance;
606 mStkContext[slotId].mActivityInstance = act;
607 // Finish the previous one if it has not been finished yet somehow.
608 if (previous != null && !previous.isDestroyed() && !previous.isFinishing()) {
609 CatLog.d(LOG_TAG, "Finish the previous pending activity - " + previous);
610 previous.finish();
611 }
612 }
Wink Savillee68857d2014-10-17 15:23:05 -0700613 break;
614 case OP_SET_DAL_INST:
615 Activity dal = new Activity();
616 CatLog.d(LOG_TAG, "Set dialog instance. " + dal);
617 dal = (Activity) msg.obj;
618 mStkContext[slotId].mDialogInstance = dal;
619 break;
Preeti Ahuja95919342013-10-01 18:18:55 -0700620 case OP_LOCALE_CHANGED:
621 CatLog.d(this, "Locale Changed");
Yuta Ui1481b172016-02-03 15:34:31 +0900622 for (int slot = PhoneConstants.SIM_ID_1; slot < mSimCount; slot++) {
623 checkForSetupEvent(LANGUAGE_SELECTION_EVENT, (Bundle) msg.obj, slot);
624 }
fionaxu805eb572017-05-02 10:57:30 -0700625 // rename all registered notification channels on locale change
626 createAllChannels();
Preeti Ahuja95919342013-10-01 18:18:55 -0700627 break;
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +0530628 case OP_ALPHA_NOTIFY:
629 handleAlphaNotify((Bundle) msg.obj);
630 break;
Preeti Ahuja560be362014-11-25 19:38:24 -0800631 case OP_IDLE_SCREEN:
632 for (int slot = 0; slot < mSimCount; slot++) {
633 if (mStkContext[slot] != null) {
634 handleIdleScreen(slot);
635 }
636 }
637 break;
Srikanth Chintala89aa6602014-03-14 16:26:57 +0530638 case OP_STOP_TONE_USER:
639 case OP_STOP_TONE:
640 CatLog.d(this, "Stop tone");
641 handleStopTone(msg, slotId);
642 break;
Wink Saville94e982b2014-07-11 07:38:14 -0700643 }
644 }
645
Wink Savillee68857d2014-10-17 15:23:05 -0700646 private void handleCardStatusChangeAndIccRefresh(Bundle args, int slotId) {
Wink Saville94e982b2014-07-11 07:38:14 -0700647 boolean cardStatus = args.getBoolean(AppInterface.CARD_STATUS);
648
Wink Savillee68857d2014-10-17 15:23:05 -0700649 CatLog.d(LOG_TAG, "CardStatus: " + cardStatus);
Wink Saville94e982b2014-07-11 07:38:14 -0700650 if (cardStatus == false) {
Wink Savillee68857d2014-10-17 15:23:05 -0700651 CatLog.d(LOG_TAG, "CARD is ABSENT");
Wink Saville94e982b2014-07-11 07:38:14 -0700652 // Uninstall STKAPP, Clear Idle text, Stop StkAppService
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +0900653 cancelIdleText(slotId);
Srikanth Chintala7c5a04c2016-09-22 19:05:01 +0530654 mStkContext[slotId].mCurrentMenu = null;
655 mStkContext[slotId].mMainCmd = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700656 if (isAllOtherCardsAbsent(slotId)) {
657 CatLog.d(LOG_TAG, "All CARDs are ABSENT");
658 StkAppInstaller.unInstall(mContext);
659 stopSelf();
660 }
Wink Saville94e982b2014-07-11 07:38:14 -0700661 } else {
662 IccRefreshResponse state = new IccRefreshResponse();
663 state.refreshResult = args.getInt(AppInterface.REFRESH_RESULT);
664
Wink Savillee68857d2014-10-17 15:23:05 -0700665 CatLog.d(LOG_TAG, "Icc Refresh Result: "+ state.refreshResult);
Wink Saville94e982b2014-07-11 07:38:14 -0700666 if ((state.refreshResult == IccRefreshResponse.REFRESH_RESULT_INIT) ||
667 (state.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET)) {
668 // Clear Idle Text
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +0900669 cancelIdleText(slotId);
Wink Saville94e982b2014-07-11 07:38:14 -0700670 }
671
672 if (state.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET) {
673 // Uninstall STkmenu
Wink Savillee68857d2014-10-17 15:23:05 -0700674 if (isAllOtherCardsAbsent(slotId)) {
675 StkAppInstaller.unInstall(mContext);
676 }
677 mStkContext[slotId].mCurrentMenu = null;
678 mStkContext[slotId].mMainCmd = null;
Wink Saville94e982b2014-07-11 07:38:14 -0700679 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800680 }
681 }
682 }
Wink Savillee68857d2014-10-17 15:23:05 -0700683 /*
684 * Check if all SIMs are absent except the id of slot equals "slotId".
685 */
686 private boolean isAllOtherCardsAbsent(int slotId) {
687 TelephonyManager mTm = (TelephonyManager) mContext.getSystemService(
688 Context.TELEPHONY_SERVICE);
689 int i = 0;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800690
Wink Savillee68857d2014-10-17 15:23:05 -0700691 for (i = 0; i < mSimCount; i++) {
692 if (i != slotId && mTm.hasIccCard(i)) {
693 break;
694 }
695 }
696 if (i == mSimCount) {
697 return true;
698 } else {
699 return false;
700 }
701 }
Preeti Ahuja95919342013-10-01 18:18:55 -0700702
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +0900703 /* package */ boolean isScreenIdle() {
704 ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
705 List<RunningTaskInfo> tasks = am.getRunningTasks(1);
706 if (tasks == null || tasks.isEmpty()) {
707 return false;
708 }
709
710 String top = tasks.get(0).topActivity.getPackageName();
711 if (top == null) {
712 return false;
713 }
714
715 // We can assume that the screen is idle if the home application is in the foreground.
716 final Intent intent = new Intent(Intent.ACTION_MAIN, null);
717 intent.addCategory(Intent.CATEGORY_HOME);
718
719 ResolveInfo info = getPackageManager().resolveActivity(intent,
720 PackageManager.MATCH_DEFAULT_ONLY);
721 if (info != null) {
722 if (top.equals(info.activityInfo.packageName)) {
723 return true;
724 }
725 }
726
727 return false;
Preeti Ahuja560be362014-11-25 19:38:24 -0800728 }
729
730 private void handleIdleScreen(int slotId) {
731
732 // If the idle screen event is present in the list need to send the
733 // response to SIM.
734 CatLog.d(this, "Need to send IDLE SCREEN Available event to SIM");
735 checkForSetupEvent(IDLE_SCREEN_AVAILABLE_EVENT, null, slotId);
736
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +0900737 if (mStkContext[slotId].mIdleModeTextCmd != null
738 && !mStkContext[slotId].mIdleModeTextVisible) {
739 launchIdleText(slotId);
Preeti Ahuja560be362014-11-25 19:38:24 -0800740 }
741 }
742
743 private void sendScreenBusyResponse(int slotId) {
744 if (mStkContext[slotId].mCurrentCmd == null) {
745 return;
746 }
747 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentCmd);
748 CatLog.d(this, "SCREEN_BUSY");
749 resMsg.setResultCode(ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS);
750 mStkService[slotId].onCmdResponse(resMsg);
751 if (mStkContext[slotId].mCmdsQ.size() != 0) {
752 callDelayedMsg(slotId);
753 } else {
754 mStkContext[slotId].mCmdInProgress = false;
755 }
756 }
757
Preeti Ahuja95919342013-10-01 18:18:55 -0700758 private void sendResponse(int resId, int slotId, boolean confirm) {
759 Message msg = mServiceHandler.obtainMessage();
760 msg.arg1 = OP_RESPONSE;
Takanori Nakano49b12722016-02-16 14:34:14 +0900761 msg.arg2 = slotId;
Preeti Ahuja95919342013-10-01 18:18:55 -0700762 Bundle args = new Bundle();
763 args.putInt(StkAppService.RES_ID, resId);
Preeti Ahuja95919342013-10-01 18:18:55 -0700764 args.putBoolean(StkAppService.CONFIRMATION, confirm);
765 msg.obj = args;
766 mServiceHandler.sendMessage(msg);
767 }
768
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700769 private boolean isCmdInteractive(CatCmdMessage cmd) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800770 switch (cmd.getCmdType()) {
771 case SEND_DTMF:
772 case SEND_SMS:
773 case SEND_SS:
774 case SEND_USSD:
775 case SET_UP_IDLE_MODE_TEXT:
776 case SET_UP_MENU:
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500777 case CLOSE_CHANNEL:
778 case RECEIVE_DATA:
779 case SEND_DATA:
Preeti Ahuja95919342013-10-01 18:18:55 -0700780 case SET_UP_EVENT_LIST:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800781 return false;
782 }
783
784 return true;
785 }
786
Wink Savillee68857d2014-10-17 15:23:05 -0700787 private void handleDelayedCmd(int slotId) {
788 CatLog.d(LOG_TAG, "handleDelayedCmd, slotId: " + slotId);
789 if (mStkContext[slotId].mCmdsQ.size() != 0) {
790 DelayedCmd cmd = mStkContext[slotId].mCmdsQ.poll();
791 if (cmd != null) {
792 CatLog.d(LOG_TAG, "handleDelayedCmd - queue size: " +
793 mStkContext[slotId].mCmdsQ.size() +
794 " id: " + cmd.id + "sim id: " + cmd.slotId);
795 switch (cmd.id) {
796 case OP_CMD:
797 handleCmd(cmd.msg, cmd.slotId);
798 break;
799 case OP_END_SESSION:
800 handleSessionEnd(cmd.slotId);
801 break;
802 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800803 }
804 }
805 }
806
Wink Savillee68857d2014-10-17 15:23:05 -0700807 private void callDelayedMsg(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800808 Message msg = mServiceHandler.obtainMessage();
809 msg.arg1 = OP_DELAYED_MSG;
Wink Savillee68857d2014-10-17 15:23:05 -0700810 msg.arg2 = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800811 mServiceHandler.sendMessage(msg);
812 }
813
Wink Savillee68857d2014-10-17 15:23:05 -0700814 private void callSetActivityInstMsg(int inst_type, int slotId, Object obj) {
815 Message msg = mServiceHandler.obtainMessage();
816 msg.obj = obj;
817 msg.arg1 = inst_type;
818 msg.arg2 = slotId;
819 mServiceHandler.sendMessage(msg);
820 }
821
822 private void handleSessionEnd(int slotId) {
Legler Wuaeefef52014-10-27 00:57:18 +0800823 // We should finish all pending activity if receiving END SESSION command.
824 cleanUpInstanceStackBySlot(slotId);
825
Wink Savillee68857d2014-10-17 15:23:05 -0700826 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
827 CatLog.d(LOG_TAG, "[handleSessionEnd] - mCurrentCmd changed to mMainCmd!.");
828 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mMainCmd;
829 CatLog.d(LOG_TAG, "slotId: " + slotId + ", mMenuState: " +
830 mStkContext[slotId].mMenuState);
831
832 mStkContext[slotId].mIsInputPending = false;
833 mStkContext[slotId].mIsMenuPending = false;
834 mStkContext[slotId].mIsDialogPending = false;
835
Wink Savillee68857d2014-10-17 15:23:05 -0700836 if (mStkContext[slotId].mMainCmd == null) {
837 CatLog.d(LOG_TAG, "[handleSessionEnd][mMainCmd is null!]");
838 }
839 mStkContext[slotId].lastSelectedItem = null;
Wink Saville79085fc2009-06-09 10:27:23 -0700840 // In case of SET UP MENU command which removed the app, don't
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800841 // update the current menu member.
Wink Savillee68857d2014-10-17 15:23:05 -0700842 if (mStkContext[slotId].mCurrentMenu != null && mStkContext[slotId].mMainCmd != null) {
843 mStkContext[slotId].mCurrentMenu = mStkContext[slotId].mMainCmd.getMenu();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800844 }
Wink Savillee68857d2014-10-17 15:23:05 -0700845 CatLog.d(LOG_TAG, "[handleSessionEnd][mMenuState]" + mStkContext[slotId].mMenuIsVisible);
Ryuto Sawada08c821c2016-08-08 18:29:02 +0900846
Wink Savillee68857d2014-10-17 15:23:05 -0700847 if (StkMenuActivity.STATE_SECONDARY == mStkContext[slotId].mMenuState) {
Ryuto Sawada08c821c2016-08-08 18:29:02 +0900848 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800849 }
Takanori Nakano3776e2c2016-10-14 16:54:28 +0900850
851 // Send a local broadcast as a notice that this service handled the session end event.
852 Intent intent = new Intent(SESSION_ENDED);
853 intent.putExtra(SLOT_ID, slotId);
854 LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
855
Wink Savillee68857d2014-10-17 15:23:05 -0700856 if (mStkContext[slotId].mCmdsQ.size() != 0) {
857 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800858 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700859 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800860 }
861 // In case a launch browser command was just confirmed, launch that url.
Wink Savillee68857d2014-10-17 15:23:05 -0700862 if (mStkContext[slotId].launchBrowser) {
863 mStkContext[slotId].launchBrowser = false;
864 launchBrowser(mStkContext[slotId].mBrowserSettings);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800865 }
866 }
867
Preeti Ahuja560be362014-11-25 19:38:24 -0800868 // returns true if any Stk related activity already has focus on the screen
Yoshiaki Nakacec55b82017-10-20 15:53:43 +0900869 boolean isTopOfStack() {
pkanwareab12f32017-02-06 08:35:03 -0800870 ActivityManager mActivityManager = (ActivityManager) mContext
Preeti Ahuja560be362014-11-25 19:38:24 -0800871 .getSystemService(ACTIVITY_SERVICE);
pkanwareab12f32017-02-06 08:35:03 -0800872 String currentPackageName = null;
873 List<RunningTaskInfo> tasks = mActivityManager.getRunningTasks(1);
874 if (tasks == null || tasks.get(0).topActivity == null) {
875 return false;
876 }
877 currentPackageName = tasks.get(0).topActivity.getPackageName();
Preeti Ahuja560be362014-11-25 19:38:24 -0800878 if (null != currentPackageName) {
879 return currentPackageName.equals(PACKAGE_NAME);
880 }
Preeti Ahuja560be362014-11-25 19:38:24 -0800881 return false;
882 }
883
Sooraj Sasindrana4160472016-10-12 16:28:25 -0700884 /**
885 * Get the boolean config from carrier config manager.
886 *
887 * @param context the context to get carrier service
888 * @param key config key defined in CarrierConfigManager
889 * @return boolean value of corresponding key.
890 */
891 private static boolean getBooleanCarrierConfig(Context context, String key) {
892 CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(
893 Context.CARRIER_CONFIG_SERVICE);
894 PersistableBundle b = null;
895 if (configManager != null) {
896 b = configManager.getConfig();
897 }
898 if (b != null) {
899 return b.getBoolean(key);
900 } else {
901 // Return static default defined in CarrierConfigManager.
902 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
903 }
904 }
905
Wink Savillee68857d2014-10-17 15:23:05 -0700906 private void handleCmd(CatCmdMessage cmdMsg, int slotId) {
Preeti Ahuja95919342013-10-01 18:18:55 -0700907
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800908 if (cmdMsg == null) {
909 return;
910 }
911 // save local reference for state tracking.
Wink Savillee68857d2014-10-17 15:23:05 -0700912 mStkContext[slotId].mCurrentCmd = cmdMsg;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800913 boolean waitForUsersResponse = true;
914
Wink Savillee68857d2014-10-17 15:23:05 -0700915 mStkContext[slotId].mIsInputPending = false;
916 mStkContext[slotId].mIsMenuPending = false;
917 mStkContext[slotId].mIsDialogPending = false;
918
919 CatLog.d(LOG_TAG,"[handleCmd]" + cmdMsg.getCmdType().name());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800920 switch (cmdMsg.getCmdType()) {
921 case DISPLAY_TEXT:
922 TextMessage msg = cmdMsg.geTextMessage();
Jeevaka Badrappan854a25c2012-12-01 16:32:03 +0200923 waitForUsersResponse = msg.responseNeeded;
Wink Savillee68857d2014-10-17 15:23:05 -0700924 if (mStkContext[slotId].lastSelectedItem != null) {
925 msg.title = mStkContext[slotId].lastSelectedItem;
926 } else if (mStkContext[slotId].mMainCmd != null){
Yoshiaki Naka28313ba2017-08-04 12:20:53 +0900927 if (!getResources().getBoolean(R.bool.show_menu_title_only_on_menu)) {
928 msg.title = mStkContext[slotId].mMainCmd.getMenu().title;
929 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800930 }
Preeti Ahuja560be362014-11-25 19:38:24 -0800931 //If we receive a low priority Display Text and the device is
932 // not displaying any STK related activity and the screen is not idle
933 // ( that is, device is in an interactive state), then send a screen busy
934 // terminal response. Otherwise display the message. The existing
935 // displayed message shall be updated with the new display text
936 // proactive command (Refer to ETSI TS 102 384 section 27.22.4.1.4.4.2).
937 if (!(msg.isHighPriority || mStkContext[slotId].mMenuIsVisible
938 || mStkContext[slotId].mDisplayTextDlgIsVisibile || isTopOfStack())) {
939 if(!isScreenIdle()) {
940 CatLog.d(LOG_TAG, "Screen is not idle");
941 sendScreenBusyResponse(slotId);
942 } else {
943 launchTextDialog(slotId);
944 }
945 } else {
946 launchTextDialog(slotId);
947 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800948 break;
949 case SELECT_ITEM:
Wink Savillee68857d2014-10-17 15:23:05 -0700950 CatLog.d(LOG_TAG, "SELECT_ITEM +");
951 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
952 mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
953 launchMenuActivity(cmdMsg.getMenu(), slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800954 break;
955 case SET_UP_MENU:
Wink Savillee68857d2014-10-17 15:23:05 -0700956 mStkContext[slotId].mCmdInProgress = false;
957 mStkContext[slotId].mMainCmd = mStkContext[slotId].mCurrentCmd;
958 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
959 mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
960 CatLog.d(LOG_TAG, "SET_UP_MENU [" + removeMenu(slotId) + "]");
961
962 if (removeMenu(slotId)) {
963 int i = 0;
964 CatLog.d(LOG_TAG, "removeMenu() - Uninstall App");
965 mStkContext[slotId].mCurrentMenu = null;
Preeti Ahuja95919342013-10-01 18:18:55 -0700966 mStkContext[slotId].mMainCmd = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700967 //Check other setup menu state. If all setup menu are removed, uninstall apk.
968 for (i = PhoneConstants.SIM_ID_1; i < mSimCount; i++) {
969 if (i != slotId
Ryuto Sawadaf51e5e02016-11-25 17:12:49 +0900970 && (mStkContext[i].mSetupMenuState == STATE_UNKNOWN
971 || mStkContext[i].mSetupMenuState == STATE_EXIST)) {
Wink Savillee68857d2014-10-17 15:23:05 -0700972 CatLog.d(LOG_TAG, "Not Uninstall App:" + i + ","
Ryuto Sawadaf51e5e02016-11-25 17:12:49 +0900973 + mStkContext[i].mSetupMenuState);
Wink Savillee68857d2014-10-17 15:23:05 -0700974 break;
975 }
976 }
977 if (i == mSimCount) {
978 StkAppInstaller.unInstall(mContext);
979 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800980 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700981 CatLog.d(LOG_TAG, "install App");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800982 StkAppInstaller.install(mContext);
983 }
Wink Savillee68857d2014-10-17 15:23:05 -0700984 if (mStkContext[slotId].mMenuIsVisible) {
985 launchMenuActivity(null, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800986 }
987 break;
988 case GET_INPUT:
989 case GET_INKEY:
Wink Savillee68857d2014-10-17 15:23:05 -0700990 launchInputActivity(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800991 break;
992 case SET_UP_IDLE_MODE_TEXT:
993 waitForUsersResponse = false;
Preeti Ahuja560be362014-11-25 19:38:24 -0800994 mStkContext[slotId].mIdleModeTextCmd = mStkContext[slotId].mCurrentCmd;
995 TextMessage idleModeText = mStkContext[slotId].mCurrentCmd.geTextMessage();
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +0900996 if (idleModeText == null || TextUtils.isEmpty(idleModeText.text)) {
997 cancelIdleText(slotId);
Preeti Ahuja560be362014-11-25 19:38:24 -0800998 }
999 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001000 if (mStkContext[slotId].mIdleModeTextCmd != null) {
1001 if (mStkContext[slotId].mIdleModeTextVisible || isScreenIdle()) {
1002 CatLog.d(this, "set up idle mode");
1003 launchIdleText(slotId);
1004 } else {
1005 registerProcessObserver();
1006 }
Preeti Ahuja560be362014-11-25 19:38:24 -08001007 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001008 break;
1009 case SEND_DTMF:
1010 case SEND_SMS:
1011 case SEND_SS:
1012 case SEND_USSD:
Preeti Ahuja95919342013-10-01 18:18:55 -07001013 case GET_CHANNEL_STATUS:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001014 waitForUsersResponse = false;
Wink Savillee68857d2014-10-17 15:23:05 -07001015 launchEventMessage(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001016 break;
1017 case LAUNCH_BROWSER:
Ryuto Sawada0bdc7192016-04-18 12:10:56 +09001018 // The device setup process should not be interrupted by launching browser.
1019 if (Settings.Global.getInt(mContext.getContentResolver(),
1020 Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
1021 CatLog.d(this, "The command is not performed if the setup has not been completed.");
1022 sendScreenBusyResponse(slotId);
1023 break;
1024 }
Sooraj Sasindrana4160472016-10-12 16:28:25 -07001025
1026 /* Check if Carrier would not want to launch browser */
1027 if (getBooleanCarrierConfig(mContext,
1028 CarrierConfigManager.KEY_STK_DISABLE_LAUNCH_BROWSER_BOOL)) {
1029 CatLog.d(this, "Browser is not launched as per carrier.");
1030 sendResponse(RES_ID_DONE, slotId, true);
1031 break;
1032 }
1033
Srikanth Chintalaba103002015-11-30 10:49:52 -08001034 mStkContext[slotId].mBrowserSettings =
1035 mStkContext[slotId].mCurrentCmd.getBrowserSettings();
1036 if (!isUrlAvailableToLaunchBrowser(mStkContext[slotId].mBrowserSettings)) {
1037 CatLog.d(this, "Browser url property is not set - send error");
1038 sendResponse(RES_ID_ERROR, slotId, true);
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07001039 } else {
Srikanth Chintalaba103002015-11-30 10:49:52 -08001040 TextMessage alphaId = mStkContext[slotId].mCurrentCmd.geTextMessage();
1041 if ((alphaId == null) || TextUtils.isEmpty(alphaId.text)) {
1042 // don't need user confirmation in this case
1043 // just launch the browser or spawn a new tab
1044 CatLog.d(this, "user confirmation is not currently needed.\n" +
1045 "supressing confirmation dialogue and confirming silently...");
1046 mStkContext[slotId].launchBrowser = true;
1047 sendResponse(RES_ID_CONFIRM, slotId, true);
1048 } else {
1049 launchConfirmationDialog(alphaId, slotId);
1050 }
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07001051 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001052 break;
1053 case SET_UP_CALL:
Preeti Ahujadd240102013-08-30 17:25:06 -07001054 TextMessage mesg = mStkContext[slotId].mCurrentCmd.getCallSettings().confirmMsg;
1055 if((mesg != null) && (mesg.text == null || mesg.text.length() == 0)) {
1056 mesg.text = getResources().getString(R.string.default_setup_call_msg);
1057 }
1058 CatLog.d(this, "SET_UP_CALL mesg.text " + mesg.text);
1059 launchConfirmationDialog(mesg, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001060 break;
1061 case PLAY_TONE:
Srikanth Chintala89aa6602014-03-14 16:26:57 +05301062 handlePlayTone(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001063 break;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001064 case OPEN_CHANNEL:
Wink Savillee68857d2014-10-17 15:23:05 -07001065 launchOpenChannelDialog(slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001066 break;
1067 case CLOSE_CHANNEL:
1068 case RECEIVE_DATA:
1069 case SEND_DATA:
Wink Savillee68857d2014-10-17 15:23:05 -07001070 TextMessage m = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001071
1072 if ((m != null) && (m.text == null)) {
1073 switch(cmdMsg.getCmdType()) {
1074 case CLOSE_CHANNEL:
1075 m.text = getResources().getString(R.string.default_close_channel_msg);
1076 break;
1077 case RECEIVE_DATA:
1078 m.text = getResources().getString(R.string.default_receive_data_msg);
1079 break;
1080 case SEND_DATA:
1081 m.text = getResources().getString(R.string.default_send_data_msg);
1082 break;
1083 }
1084 }
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001085 /*
1086 * Display indication in the form of a toast to the user if required.
1087 */
Wink Savillee68857d2014-10-17 15:23:05 -07001088 launchEventMessage(slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001089 break;
Preeti Ahuja95919342013-10-01 18:18:55 -07001090 case SET_UP_EVENT_LIST:
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001091 replaceEventList(slotId);
Preeti Ahuja560be362014-11-25 19:38:24 -08001092 if (isScreenIdle()) {
1093 CatLog.d(this," Check if IDLE_SCREEN_AVAILABLE_EVENT is present in List");
1094 checkForSetupEvent(IDLE_SCREEN_AVAILABLE_EVENT, null, slotId);
1095 }
Preeti Ahuja95919342013-10-01 18:18:55 -07001096 break;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001097 }
1098
1099 if (!waitForUsersResponse) {
Wink Savillee68857d2014-10-17 15:23:05 -07001100 if (mStkContext[slotId].mCmdsQ.size() != 0) {
1101 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001102 } else {
Wink Savillee68857d2014-10-17 15:23:05 -07001103 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001104 }
1105 }
1106 }
1107
Wink Savillee68857d2014-10-17 15:23:05 -07001108 private void handleCmdResponse(Bundle args, int slotId) {
1109 CatLog.d(LOG_TAG, "handleCmdResponse, sim id: " + slotId);
1110 if (mStkContext[slotId].mCurrentCmd == null) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001111 return;
1112 }
Wink Savillee68857d2014-10-17 15:23:05 -07001113
1114 if (mStkService[slotId] == null) {
Legler Wuaeefef52014-10-27 00:57:18 +08001115 mStkService[slotId] = CatService.getInstance(slotId);
Wink Savillee68857d2014-10-17 15:23:05 -07001116 if (mStkService[slotId] == null) {
Alex Yakavenkad8e2ecd2012-04-20 17:10:15 -07001117 // This should never happen (we should be responding only to a message
1118 // that arrived from StkService). It has to exist by this time
Wink Savillee68857d2014-10-17 15:23:05 -07001119 CatLog.d(LOG_TAG, "Exception! mStkService is null when we need to send response.");
Alex Yakavenkad8e2ecd2012-04-20 17:10:15 -07001120 throw new RuntimeException("mStkService is null when we need to send response");
1121 }
1122 }
1123
Wink Savillee68857d2014-10-17 15:23:05 -07001124 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentCmd);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001125
1126 // set result code
1127 boolean helpRequired = args.getBoolean(HELP, false);
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001128 boolean confirmed = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001129
1130 switch(args.getInt(RES_ID)) {
1131 case RES_ID_MENU_SELECTION:
Wink Savillee68857d2014-10-17 15:23:05 -07001132 CatLog.d(LOG_TAG, "MENU_SELECTION=" + mStkContext[slotId].
1133 mCurrentMenuCmd.getCmdType());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001134 int menuSelection = args.getInt(MENU_SELECTION);
Wink Savillee68857d2014-10-17 15:23:05 -07001135 switch(mStkContext[slotId].mCurrentMenuCmd.getCmdType()) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001136 case SET_UP_MENU:
1137 case SELECT_ITEM:
Wink Savillee68857d2014-10-17 15:23:05 -07001138 mStkContext[slotId].lastSelectedItem = getItemName(menuSelection, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001139 if (helpRequired) {
1140 resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
1141 } else {
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301142 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1143 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001144 }
1145 resMsg.setMenuSelection(menuSelection);
1146 break;
1147 }
1148 break;
1149 case RES_ID_INPUT:
Wink Savillee68857d2014-10-17 15:23:05 -07001150 CatLog.d(LOG_TAG, "RES_ID_INPUT");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001151 String input = args.getString(INPUT);
Wink Savillee68857d2014-10-17 15:23:05 -07001152 if (input != null && (null != mStkContext[slotId].mCurrentCmd.geInput()) &&
1153 (mStkContext[slotId].mCurrentCmd.geInput().yesNo)) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001154 boolean yesNoSelection = input
1155 .equals(StkInputActivity.YES_STR_RESPONSE);
1156 resMsg.setYesNo(yesNoSelection);
1157 } else {
1158 if (helpRequired) {
1159 resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
1160 } else {
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301161 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1162 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001163 resMsg.setInput(input);
1164 }
1165 }
1166 break;
1167 case RES_ID_CONFIRM:
Alex Yakavenkad41f1d92010-07-12 14:13:13 -07001168 CatLog.d(this, "RES_ID_CONFIRM");
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001169 confirmed = args.getBoolean(CONFIRMATION);
Wink Savillee68857d2014-10-17 15:23:05 -07001170 switch (mStkContext[slotId].mCurrentCmd.getCmdType()) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001171 case DISPLAY_TEXT:
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301172 if (confirmed) {
1173 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1174 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
1175 } else {
1176 resMsg.setResultCode(ResultCode.UICC_SESSION_TERM_BY_USER);
1177 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001178 break;
1179 case LAUNCH_BROWSER:
1180 resMsg.setResultCode(confirmed ? ResultCode.OK
1181 : ResultCode.UICC_SESSION_TERM_BY_USER);
1182 if (confirmed) {
Wink Savillee68857d2014-10-17 15:23:05 -07001183 mStkContext[slotId].launchBrowser = true;
1184 mStkContext[slotId].mBrowserSettings =
1185 mStkContext[slotId].mCurrentCmd.getBrowserSettings();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001186 }
1187 break;
1188 case SET_UP_CALL:
1189 resMsg.setResultCode(ResultCode.OK);
1190 resMsg.setConfirmation(confirmed);
1191 if (confirmed) {
Wink Savillee68857d2014-10-17 15:23:05 -07001192 launchEventMessage(slotId,
1193 mStkContext[slotId].mCurrentCmd.getCallSettings().callMsg);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001194 }
1195 break;
1196 }
1197 break;
1198 case RES_ID_DONE:
1199 resMsg.setResultCode(ResultCode.OK);
1200 break;
1201 case RES_ID_BACKWARD:
Wink Savillee68857d2014-10-17 15:23:05 -07001202 CatLog.d(LOG_TAG, "RES_ID_BACKWARD");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001203 resMsg.setResultCode(ResultCode.BACKWARD_MOVE_BY_USER);
1204 break;
1205 case RES_ID_END_SESSION:
Wink Savillee68857d2014-10-17 15:23:05 -07001206 CatLog.d(LOG_TAG, "RES_ID_END_SESSION");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001207 resMsg.setResultCode(ResultCode.UICC_SESSION_TERM_BY_USER);
1208 break;
1209 case RES_ID_TIMEOUT:
Wink Savillee68857d2014-10-17 15:23:05 -07001210 CatLog.d(LOG_TAG, "RES_ID_TIMEOUT");
Naveen Kallad5176892009-11-30 12:45:29 -08001211 // GCF test-case 27.22.4.1.1 Expected Sequence 1.5 (DISPLAY TEXT,
1212 // Clear message after delay, successful) expects result code OK.
1213 // If the command qualifier specifies no user response is required
1214 // then send OK instead of NO_RESPONSE_FROM_USER
Wink Savillee68857d2014-10-17 15:23:05 -07001215 if ((mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1216 AppInterface.CommandType.DISPLAY_TEXT.value())
1217 && (mStkContext[slotId].mCurrentCmd.geTextMessage().userClear == false)) {
Naveen Kallad5176892009-11-30 12:45:29 -08001218 resMsg.setResultCode(ResultCode.OK);
1219 } else {
1220 resMsg.setResultCode(ResultCode.NO_RESPONSE_FROM_USER);
1221 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001222 break;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001223 case RES_ID_CHOICE:
1224 int choice = args.getInt(CHOICE);
1225 CatLog.d(this, "User Choice=" + choice);
1226 switch (choice) {
1227 case YES:
1228 resMsg.setResultCode(ResultCode.OK);
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001229 confirmed = true;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001230 break;
1231 case NO:
1232 resMsg.setResultCode(ResultCode.USER_NOT_ACCEPT);
1233 break;
1234 }
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001235
Wink Savillee68857d2014-10-17 15:23:05 -07001236 if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1237 AppInterface.CommandType.OPEN_CHANNEL.value()) {
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001238 resMsg.setConfirmation(confirmed);
1239 }
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001240 break;
Srikanth Chintalaba103002015-11-30 10:49:52 -08001241 case RES_ID_ERROR:
1242 CatLog.d(LOG_TAG, "RES_ID_ERROR");
1243 switch (mStkContext[slotId].mCurrentCmd.getCmdType()) {
1244 case LAUNCH_BROWSER:
1245 resMsg.setResultCode(ResultCode.LAUNCH_BROWSER_ERROR);
1246 break;
1247 }
1248 break;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001249 default:
Wink Savillee68857d2014-10-17 15:23:05 -07001250 CatLog.d(LOG_TAG, "Unknown result id");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001251 return;
1252 }
Wink Savillee68857d2014-10-17 15:23:05 -07001253
1254 if (null != mStkContext[slotId].mCurrentCmd &&
1255 null != mStkContext[slotId].mCurrentCmd.getCmdType()) {
1256 CatLog.d(LOG_TAG, "handleCmdResponse- cmdName[" +
1257 mStkContext[slotId].mCurrentCmd.getCmdType().name() + "]");
1258 }
1259 mStkService[slotId].onCmdResponse(resMsg);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001260 }
1261
1262 /**
1263 * Returns 0 or FLAG_ACTIVITY_NO_USER_ACTION, 0 means the user initiated the action.
1264 *
1265 * @param userAction If the userAction is yes then we always return 0 otherwise
1266 * mMenuIsVisible is used to determine what to return. If mMenuIsVisible is true
1267 * then we are the foreground app and we'll return 0 as from our perspective a
1268 * user action did cause. If it's false than we aren't the foreground app and
1269 * FLAG_ACTIVITY_NO_USER_ACTION is returned.
Wink Saville79085fc2009-06-09 10:27:23 -07001270 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001271 * @return 0 or FLAG_ACTIVITY_NO_USER_ACTION
1272 */
Wink Savillee68857d2014-10-17 15:23:05 -07001273 private int getFlagActivityNoUserAction(InitiatedByUserAction userAction, int slotId) {
1274 return ((userAction == InitiatedByUserAction.yes) | mStkContext[slotId].mMenuIsVisible)
1275 ? 0 : Intent.FLAG_ACTIVITY_NO_USER_ACTION;
1276 }
1277 /**
1278 * This method is used for cleaning up pending instances in stack.
1279 */
1280 private void cleanUpInstanceStackBySlot(int slotId) {
1281 Activity activity = mStkContext[slotId].getPendingActivityInstance();
1282 Activity dialog = mStkContext[slotId].getPendingDialogInstance();
1283 CatLog.d(LOG_TAG, "cleanUpInstanceStackBySlot slotId: " + slotId);
Legler Wuaeefef52014-10-27 00:57:18 +08001284 if (mStkContext[slotId].mCurrentCmd == null) {
1285 CatLog.d(LOG_TAG, "current cmd is null.");
1286 return;
1287 }
Wink Savillee68857d2014-10-17 15:23:05 -07001288 if (activity != null) {
1289 CatLog.d(LOG_TAG, "current cmd type: " +
1290 mStkContext[slotId].mCurrentCmd.getCmdType());
1291 if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1292 AppInterface.CommandType.GET_INPUT.value() ||
1293 mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1294 AppInterface.CommandType.GET_INKEY.value()) {
1295 mStkContext[slotId].mIsInputPending = true;
1296 } else if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1297 AppInterface.CommandType.SET_UP_MENU.value() ||
1298 mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1299 AppInterface.CommandType.SELECT_ITEM.value()) {
1300 mStkContext[slotId].mIsMenuPending = true;
1301 } else {
1302 }
1303 CatLog.d(LOG_TAG, "finish pending activity.");
1304 activity.finish();
1305 mStkContext[slotId].mActivityInstance = null;
1306 }
1307 if (dialog != null) {
1308 CatLog.d(LOG_TAG, "finish pending dialog.");
1309 mStkContext[slotId].mIsDialogPending = true;
1310 dialog.finish();
1311 mStkContext[slotId].mDialogInstance = null;
1312 }
1313 }
1314 /**
1315 * This method is used for restoring pending instances from stack.
1316 */
1317 private void restoreInstanceFromStackBySlot(int slotId) {
1318 AppInterface.CommandType cmdType = mStkContext[slotId].mCurrentCmd.getCmdType();
1319
1320 CatLog.d(LOG_TAG, "restoreInstanceFromStackBySlot cmdType : " + cmdType);
1321 switch(cmdType) {
1322 case GET_INPUT:
1323 case GET_INKEY:
1324 launchInputActivity(slotId);
1325 //Set mMenuIsVisible to true for showing main menu for
1326 //following session end command.
1327 mStkContext[slotId].mMenuIsVisible = true;
1328 break;
1329 case DISPLAY_TEXT:
1330 launchTextDialog(slotId);
1331 break;
1332 case LAUNCH_BROWSER:
1333 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.geTextMessage(),
1334 slotId);
1335 break;
1336 case OPEN_CHANNEL:
1337 launchOpenChannelDialog(slotId);
1338 break;
1339 case SET_UP_CALL:
1340 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.getCallSettings().
1341 confirmMsg, slotId);
1342 break;
1343 case SET_UP_MENU:
1344 case SELECT_ITEM:
1345 launchMenuActivity(null, slotId);
1346 break;
1347 default:
1348 break;
1349 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001350 }
1351
Wink Savillee68857d2014-10-17 15:23:05 -07001352 private void launchMenuActivity(Menu menu, int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001353 Intent newIntent = new Intent(Intent.ACTION_VIEW);
Wink Savillee68857d2014-10-17 15:23:05 -07001354 String targetActivity = STK_MENU_ACTIVITY_NAME;
1355 String uriString = STK_MENU_URI + System.currentTimeMillis();
1356 //Set unique URI to create a new instance of activity for different slotId.
1357 Uri uriData = Uri.parse(uriString);
1358
1359 CatLog.d(LOG_TAG, "launchMenuActivity, slotId: " + slotId + " , " +
1360 uriData.toString() + " , " + mStkContext[slotId].mOpCode + ", "
1361 + mStkContext[slotId].mMenuState);
1362 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1363 int intentFlags = Intent.FLAG_ACTIVITY_NEW_TASK;
1364
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001365 if (menu == null) {
1366 // We assume this was initiated by the user pressing the tool kit icon
Wink Savillee68857d2014-10-17 15:23:05 -07001367 intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.yes, slotId);
Wink Savillee68857d2014-10-17 15:23:05 -07001368 //If the last pending menu is secondary menu, "STATE" should be "STATE_SECONDARY".
1369 //Otherwise, it should be "STATE_MAIN".
1370 if (mStkContext[slotId].mOpCode == OP_LAUNCH_APP &&
1371 mStkContext[slotId].mMenuState == StkMenuActivity.STATE_SECONDARY) {
1372 newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
1373 } else {
1374 newIntent.putExtra("STATE", StkMenuActivity.STATE_MAIN);
1375 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
1376 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001377 } else {
1378 // We don't know and we'll let getFlagActivityNoUserAction decide.
Wink Savillee68857d2014-10-17 15:23:05 -07001379 intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001380 newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
Wink Savillee68857d2014-10-17 15:23:05 -07001381 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_SECONDARY;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001382 }
Wink Savillee68857d2014-10-17 15:23:05 -07001383 newIntent.putExtra(SLOT_ID, slotId);
1384 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001385 newIntent.setFlags(intentFlags);
1386 mContext.startActivity(newIntent);
1387 }
1388
Wink Savillee68857d2014-10-17 15:23:05 -07001389 private void launchInputActivity(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001390 Intent newIntent = new Intent(Intent.ACTION_VIEW);
Wink Savillee68857d2014-10-17 15:23:05 -07001391 String targetActivity = STK_INPUT_ACTIVITY_NAME;
1392 String uriString = STK_INPUT_URI + System.currentTimeMillis();
1393 //Set unique URI to create a new instance of activity for different slotId.
1394 Uri uriData = Uri.parse(uriString);
1395
1396 CatLog.d(LOG_TAG, "launchInputActivity, slotId: " + slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001397 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
Wink Savillee68857d2014-10-17 15:23:05 -07001398 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1399 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1400 newIntent.putExtra("INPUT", mStkContext[slotId].mCurrentCmd.geInput());
1401 newIntent.putExtra(SLOT_ID, slotId);
1402 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001403 mContext.startActivity(newIntent);
1404 }
1405
Wink Savillee68857d2014-10-17 15:23:05 -07001406 private void launchTextDialog(int slotId) {
1407 CatLog.d(LOG_TAG, "launchTextDialog, slotId: " + slotId);
1408 Intent newIntent = new Intent();
1409 String targetActivity = STK_DIALOG_ACTIVITY_NAME;
1410 int action = getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
1411 String uriString = STK_DIALOG_URI + System.currentTimeMillis();
1412 //Set unique URI to create a new instance of activity for different slotId.
1413 Uri uriData = Uri.parse(uriString);
1414 if (newIntent != null) {
1415 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1416 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1417 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
1418 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1419 newIntent.setData(uriData);
1420 newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
1421 newIntent.putExtra(SLOT_ID, slotId);
1422 startActivity(newIntent);
Preeti Ahuja414bc412013-06-25 19:31:49 -07001423 // For display texts with immediate response, send the terminal response
1424 // immediately. responseNeeded will be false, if display text command has
1425 // the immediate response tlv.
1426 if (!mStkContext[slotId].mCurrentCmd.geTextMessage().responseNeeded) {
1427 sendResponse(RES_ID_CONFIRM, slotId, true);
1428 }
Wink Savillee68857d2014-10-17 15:23:05 -07001429 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001430 }
1431
Wink Savillee68857d2014-10-17 15:23:05 -07001432 public boolean isStkDialogActivated(Context context) {
1433 String stkDialogActivity = "com.android.stk.StkDialogActivity";
1434 boolean activated = false;
1435 final ActivityManager am = (ActivityManager) context.getSystemService(
1436 Context.ACTIVITY_SERVICE);
1437 String topActivity = am.getRunningTasks(1).get(0).topActivity.getClassName();
1438
1439 CatLog.d(LOG_TAG, "isStkDialogActivated: " + topActivity);
1440 if (topActivity.equals(stkDialogActivity)) {
1441 activated = true;
1442 }
1443 CatLog.d(LOG_TAG, "activated : " + activated);
1444 return activated;
Johan Hellman3aec01c2011-02-10 10:15:28 +01001445 }
1446
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001447 private void replaceEventList(int slotId) {
1448 if (mStkContext[slotId].mSetupEventListSettings != null) {
1449 for (int current : mStkContext[slotId].mSetupEventListSettings.eventList) {
1450 if (current != INVALID_SETUP_EVENT) {
1451 // Cancel the event notification if it is not listed in the new event list.
1452 if ((mStkContext[slotId].mCurrentCmd.getSetEventList() == null)
1453 || !findEvent(current, mStkContext[slotId].mCurrentCmd
1454 .getSetEventList().eventList)) {
1455 unregisterEvent(current, slotId);
1456 }
1457 }
1458 }
1459 }
1460 mStkContext[slotId].mSetupEventListSettings
1461 = mStkContext[slotId].mCurrentCmd.getSetEventList();
1462 mStkContext[slotId].mCurrentSetupEventCmd = mStkContext[slotId].mCurrentCmd;
1463 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
1464 registerEvents(slotId);
1465 }
1466
1467 private boolean findEvent(int event, int[] eventList) {
1468 for (int content : eventList) {
1469 if (content == event) return true;
1470 }
1471 return false;
1472 }
1473
1474 private void unregisterEvent(int event, int slotId) {
1475 switch (event) {
1476 case IDLE_SCREEN_AVAILABLE_EVENT:
1477 unregisterProcessObserver(AppInterface.CommandType.SET_UP_EVENT_LIST, slotId);
1478 break;
1479 case LANGUAGE_SELECTION_EVENT:
1480 default:
1481 break;
1482 }
1483 }
1484
1485 private void registerEvents(int slotId) {
1486 if (mStkContext[slotId].mSetupEventListSettings == null) {
1487 return;
1488 }
1489 for (int event : mStkContext[slotId].mSetupEventListSettings.eventList) {
1490 switch (event) {
1491 case IDLE_SCREEN_AVAILABLE_EVENT:
1492 registerProcessObserver();
1493 break;
1494 case LANGUAGE_SELECTION_EVENT:
1495 default:
1496 break;
1497 }
1498 }
1499 }
1500
1501 private synchronized void registerProcessObserver() {
1502 if (mProcessObserver == null) {
1503 try {
1504 IProcessObserver.Stub observer = new IProcessObserver.Stub() {
1505 @Override
1506 public void onForegroundActivitiesChanged(int pid, int uid, boolean fg) {
1507 if (isScreenIdle()) {
1508 Message message = mServiceHandler.obtainMessage();
1509 message.arg1 = OP_IDLE_SCREEN;
1510 mServiceHandler.sendMessage(message);
1511 unregisterProcessObserver();
1512 }
1513 }
1514
1515 @Override
1516 public void onProcessDied(int pid, int uid) {
1517 }
1518 };
1519 ActivityManagerNative.getDefault().registerProcessObserver(observer);
1520 mProcessObserver = observer;
1521 } catch (RemoteException e) {
1522 CatLog.d(this, "Failed to register the process observer");
1523 }
1524 }
1525 }
1526
1527 private void unregisterProcessObserver(AppInterface.CommandType command, int slotId) {
1528 // Check if there is any pending command which still needs the process observer
1529 // except for the current command and slot.
1530 for (int slot = PhoneConstants.SIM_ID_1; slot < mSimCount; slot++) {
1531 if (command != AppInterface.CommandType.SET_UP_IDLE_MODE_TEXT || slot != slotId) {
1532 if (mStkContext[slot].mIdleModeTextCmd != null
1533 && !mStkContext[slot].mIdleModeTextVisible) {
1534 // Keep the process observer registered
1535 // as there is an idle mode text which has not been visible yet.
1536 return;
1537 }
1538 }
1539 if (command != AppInterface.CommandType.SET_UP_EVENT_LIST || slot != slotId) {
1540 if (mStkContext[slot].mSetupEventListSettings != null) {
1541 if (findEvent(IDLE_SCREEN_AVAILABLE_EVENT,
1542 mStkContext[slot].mSetupEventListSettings.eventList)) {
1543 // Keep the process observer registered
1544 // as there is a SIM card which still want IDLE SCREEN AVAILABLE event.
1545 return;
1546 }
1547 }
1548 }
1549 }
1550 unregisterProcessObserver();
1551 }
1552
1553 private synchronized void unregisterProcessObserver() {
1554 if (mProcessObserver != null) {
1555 try {
1556 ActivityManagerNative.getDefault().unregisterProcessObserver(mProcessObserver);
1557 mProcessObserver = null;
1558 } catch (RemoteException e) {
1559 CatLog.d(this, "Failed to unregister the process observer");
1560 }
1561 }
1562 }
1563
Preeti Ahuja95919342013-10-01 18:18:55 -07001564 private void sendSetUpEventResponse(int event, byte[] addedInfo, int slotId) {
Preeti Ahuja414bc412013-06-25 19:31:49 -07001565 CatLog.d(this, "sendSetUpEventResponse: event : " + event + "slotId = " + slotId);
Preeti Ahuja95919342013-10-01 18:18:55 -07001566
1567 if (mStkContext[slotId].mCurrentSetupEventCmd == null){
1568 CatLog.e(this, "mCurrentSetupEventCmd is null");
1569 return;
1570 }
1571
1572 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentSetupEventCmd);
1573
1574 resMsg.setResultCode(ResultCode.OK);
1575 resMsg.setEventDownload(event, addedInfo);
1576
1577 mStkService[slotId].onCmdResponse(resMsg);
1578 }
1579
1580 private void checkForSetupEvent(int event, Bundle args, int slotId) {
1581 boolean eventPresent = false;
1582 byte[] addedInfo = null;
1583 CatLog.d(this, "Event :" + event);
1584
1585 if (mStkContext[slotId].mSetupEventListSettings != null) {
1586 /* Checks if the event is present in the EventList updated by last
1587 * SetupEventList Proactive Command */
1588 for (int i : mStkContext[slotId].mSetupEventListSettings.eventList) {
1589 if (event == i) {
1590 eventPresent = true;
1591 break;
1592 }
1593 }
1594
1595 /* If Event is present send the response to ICC */
1596 if (eventPresent == true) {
1597 CatLog.d(this, " Event " + event + "exists in the EventList");
1598
1599 switch (event) {
Preeti Ahuja560be362014-11-25 19:38:24 -08001600 case IDLE_SCREEN_AVAILABLE_EVENT:
1601 sendSetUpEventResponse(event, addedInfo, slotId);
1602 removeSetUpEvent(event, slotId);
1603 break;
Preeti Ahuja95919342013-10-01 18:18:55 -07001604 case LANGUAGE_SELECTION_EVENT:
1605 String language = mContext
1606 .getResources().getConfiguration().locale.getLanguage();
1607 CatLog.d(this, "language: " + language);
1608 // Each language code is a pair of alpha-numeric characters.
1609 // Each alpha-numeric character shall be coded on one byte
1610 // using the SMS default 7-bit coded alphabet
1611 addedInfo = GsmAlphabet.stringToGsm8BitPacked(language);
1612 sendSetUpEventResponse(event, addedInfo, slotId);
1613 break;
1614 default:
1615 break;
1616 }
1617 } else {
1618 CatLog.e(this, " Event does not exist in the EventList");
1619 }
1620 } else {
1621 CatLog.e(this, "SetupEventList is not received. Ignoring the event: " + event);
1622 }
1623 }
1624
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001625 private void removeSetUpEvent(int event, int slotId) {
Preeti Ahuja95919342013-10-01 18:18:55 -07001626 CatLog.d(this, "Remove Event :" + event);
1627
1628 if (mStkContext[slotId].mSetupEventListSettings != null) {
1629 /*
1630 * Make new Eventlist without the event
1631 */
1632 for (int i = 0; i < mStkContext[slotId].mSetupEventListSettings.eventList.length; i++) {
1633 if (event == mStkContext[slotId].mSetupEventListSettings.eventList[i]) {
1634 mStkContext[slotId].mSetupEventListSettings.eventList[i] = INVALID_SETUP_EVENT;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001635
1636 switch (event) {
1637 case IDLE_SCREEN_AVAILABLE_EVENT:
1638 // The process observer can be unregistered
1639 // as the idle screen has already been available.
1640 unregisterProcessObserver();
1641 break;
1642 default:
1643 break;
1644 }
Preeti Ahuja95919342013-10-01 18:18:55 -07001645 break;
1646 }
1647 }
1648 }
1649 }
1650
1651 private void launchEventMessage(int slotId) {
1652 launchEventMessage(slotId, mStkContext[slotId].mCurrentCmd.geTextMessage());
1653 }
1654
Wink Savillee68857d2014-10-17 15:23:05 -07001655 private void launchEventMessage(int slotId, TextMessage msg) {
Ryuto Sawada2ba20cc2015-12-28 17:10:35 +01001656 if (msg == null || msg.text == null || (msg.text != null && msg.text.length() == 0)) {
Wink Savillee68857d2014-10-17 15:23:05 -07001657 CatLog.d(LOG_TAG, "launchEventMessage return");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001658 return;
1659 }
Wink Savillee68857d2014-10-17 15:23:05 -07001660
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001661 Toast toast = new Toast(mContext.getApplicationContext());
1662 LayoutInflater inflate = (LayoutInflater) mContext
1663 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
1664 View v = inflate.inflate(R.layout.stk_event_msg, null);
1665 TextView tv = (TextView) v
1666 .findViewById(com.android.internal.R.id.message);
1667 ImageView iv = (ImageView) v
1668 .findViewById(com.android.internal.R.id.icon);
1669 if (msg.icon != null) {
1670 iv.setImageBitmap(msg.icon);
1671 } else {
1672 iv.setVisibility(View.GONE);
1673 }
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301674 /* In case of 'self explanatory' stkapp should display the specified
1675 * icon in proactive command (but not the alpha string).
1676 * If icon is non-self explanatory and if the icon could not be displayed
1677 * then alpha string or text data should be displayed
1678 * Ref: ETSI 102.223,section 6.5.4
1679 */
1680 if (mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ||
1681 msg.icon == null || !msg.iconSelfExplanatory) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001682 tv.setText(msg.text);
1683 }
1684
1685 toast.setView(v);
1686 toast.setDuration(Toast.LENGTH_LONG);
1687 toast.setGravity(Gravity.BOTTOM, 0, 0);
1688 toast.show();
1689 }
1690
Wink Savillee68857d2014-10-17 15:23:05 -07001691 private void launchConfirmationDialog(TextMessage msg, int slotId) {
1692 msg.title = mStkContext[slotId].lastSelectedItem;
1693 Intent newIntent = new Intent();
1694 String targetActivity = STK_DIALOG_ACTIVITY_NAME;
1695 String uriString = STK_DIALOG_URI + System.currentTimeMillis();
1696 //Set unique URI to create a new instance of activity for different slotId.
1697 Uri uriData = Uri.parse(uriString);
1698
1699 if (newIntent != null) {
1700 newIntent.setClassName(this, targetActivity);
1701 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1702 | Intent.FLAG_ACTIVITY_NO_HISTORY
1703 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
1704 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1705 newIntent.putExtra("TEXT", msg);
1706 newIntent.putExtra(SLOT_ID, slotId);
1707 newIntent.setData(uriData);
1708 startActivity(newIntent);
1709 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001710 }
1711
1712 private void launchBrowser(BrowserSettings settings) {
1713 if (settings == null) {
1714 return;
1715 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001716
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001717 Uri data = null;
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07001718 String url;
1719 if (settings.url == null) {
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001720 // if the command did not contain a URL,
1721 // launch the browser to the default homepage.
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07001722 CatLog.d(this, "no url data provided by proactive command." +
1723 " launching browser with stk default URL ... ");
1724 url = SystemProperties.get(STK_BROWSER_DEFAULT_URL_SYSPROP,
1725 "http://www.google.com");
1726 } else {
1727 CatLog.d(this, "launch browser command has attached url = " + settings.url);
1728 url = settings.url;
Abhishek Adappa840c82f2013-02-26 10:19:49 -08001729 }
David Brown7c03cfe2011-10-20 15:36:12 -07001730
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07001731 if (url.startsWith("http://") || url.startsWith("https://")) {
1732 data = Uri.parse(url);
1733 CatLog.d(this, "launching browser with url = " + url);
1734 } else {
1735 String modifiedUrl = "http://" + url;
1736 data = Uri.parse(modifiedUrl);
1737 CatLog.d(this, "launching browser with modified url = " + modifiedUrl);
1738 }
1739
1740 Intent intent = new Intent(Intent.ACTION_VIEW);
1741 intent.setData(data);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001742 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1743 switch (settings.mode) {
1744 case USE_EXISTING_BROWSER:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001745 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1746 break;
1747 case LAUNCH_NEW_BROWSER:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001748 intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
1749 break;
1750 case LAUNCH_IF_NOT_ALREADY_LAUNCHED:
1751 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
1752 break;
1753 }
1754 // start browser activity
1755 startActivity(intent);
1756 // a small delay, let the browser start, before processing the next command.
Wink Saville79085fc2009-06-09 10:27:23 -07001757 // this is good for scenarios where a related DISPLAY TEXT command is
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001758 // followed immediately.
1759 try {
Ryuto Sawada350aaa62016-06-13 14:47:22 +09001760 Thread.sleep(3000);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001761 } catch (InterruptedException e) {}
1762 }
1763
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001764 private void cancelIdleText(int slotId) {
1765 unregisterProcessObserver(AppInterface.CommandType.SET_UP_IDLE_MODE_TEXT, slotId);
1766 mNotificationManager.cancel(getNotificationId(slotId));
1767 mStkContext[slotId].mIdleModeTextCmd = null;
1768 mStkContext[slotId].mIdleModeTextVisible = false;
1769 }
1770
Wink Savillee68857d2014-10-17 15:23:05 -07001771 private void launchIdleText(int slotId) {
Preeti Ahuja560be362014-11-25 19:38:24 -08001772 TextMessage msg = mStkContext[slotId].mIdleModeTextCmd.geTextMessage();
dujin.cha2a0eb2a2011-11-11 15:03:57 +09001773
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001774 if (msg != null && !TextUtils.isEmpty(msg.text)) {
Preeti Ahuja95919342013-10-01 18:18:55 -07001775 CatLog.d(LOG_TAG, "launchIdleText - text[" + msg.text
1776 + "] iconSelfExplanatory[" + msg.iconSelfExplanatory
1777 + "] icon[" + msg.icon + "], sim id: " + slotId);
Wink Savillee68857d2014-10-17 15:23:05 -07001778 CatLog.d(LOG_TAG, "Add IdleMode text");
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001779 PendingIntent pendingIntent = PendingIntent.getService(mContext, 0,
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001780 new Intent(mContext, StkAppService.class), 0);
fionaxu805eb572017-05-02 10:57:30 -07001781 createAllChannels();
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001782 final Notification.Builder notificationBuilder = new Notification.Builder(
fionaxu2c91c752017-04-21 18:11:57 -07001783 StkAppService.this, STK_NOTIFICATION_CHANNEL_ID);
Wink Savillee68857d2014-10-17 15:23:05 -07001784 if (mStkContext[slotId].mMainCmd != null &&
1785 mStkContext[slotId].mMainCmd.getMenu() != null) {
1786 notificationBuilder.setContentTitle(mStkContext[slotId].mMainCmd.getMenu().title);
Christopher Posselwhite2ad2ab72013-05-27 07:51:06 +02001787 } else {
1788 notificationBuilder.setContentTitle("");
1789 }
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001790 notificationBuilder
1791 .setSmallIcon(com.android.internal.R.drawable.stat_notify_sim_toolkit);
1792 notificationBuilder.setContentIntent(pendingIntent);
1793 notificationBuilder.setOngoing(true);
1794 // Set text and icon for the status bar and notification body.
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301795 if (mStkContext[slotId].mIdleModeTextCmd.hasIconLoadFailed() ||
1796 !msg.iconSelfExplanatory) {
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001797 notificationBuilder.setContentText(msg.text);
Christopher Posselwhite2ad2ab72013-05-27 07:51:06 +02001798 notificationBuilder.setTicker(msg.text);
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01001799 }
1800 if (msg.icon != null) {
1801 notificationBuilder.setLargeIcon(msg.icon);
1802 } else {
1803 Bitmap bitmapIcon = BitmapFactory.decodeResource(StkAppService.this
1804 .getResources().getSystem(),
1805 com.android.internal.R.drawable.stat_notify_sim_toolkit);
1806 notificationBuilder.setLargeIcon(bitmapIcon);
1807 }
Selim Cinek62eb3fe2014-08-27 17:52:23 +02001808 notificationBuilder.setColor(mContext.getResources().getColor(
1809 com.android.internal.R.color.system_notification_accent_color));
Wink Savillee68857d2014-10-17 15:23:05 -07001810 mNotificationManager.notify(getNotificationId(slotId), notificationBuilder.build());
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001811 mStkContext[slotId].mIdleModeTextVisible = true;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001812 }
1813 }
1814
fionaxu805eb572017-05-02 10:57:30 -07001815 /** Creates the notification channel and registers it with NotificationManager.
1816 * If a channel with the same ID is already registered, NotificationManager will
1817 * ignore this call.
1818 */
1819 private void createAllChannels() {
1820 mNotificationManager.createNotificationChannel(new NotificationChannel(
1821 STK_NOTIFICATION_CHANNEL_ID,
1822 getResources().getString(R.string.stk_channel_name),
1823 NotificationManager.IMPORTANCE_MIN));
1824 }
1825
Wink Savillee68857d2014-10-17 15:23:05 -07001826 private void launchToneDialog(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001827 Intent newIntent = new Intent(this, ToneDialog.class);
Wink Savillee68857d2014-10-17 15:23:05 -07001828 String uriString = STK_TONE_URI + slotId;
1829 Uri uriData = Uri.parse(uriString);
1830 //Set unique URI to create a new instance of activity for different slotId.
1831 CatLog.d(LOG_TAG, "launchToneDialog, slotId: " + slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001832 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1833 | Intent.FLAG_ACTIVITY_NO_HISTORY
1834 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
Wink Savillee68857d2014-10-17 15:23:05 -07001835 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1836 newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
1837 newIntent.putExtra("TONE", mStkContext[slotId].mCurrentCmd.getToneSettings());
1838 newIntent.putExtra(SLOT_ID, slotId);
1839 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001840 startActivity(newIntent);
1841 }
1842
Srikanth Chintala89aa6602014-03-14 16:26:57 +05301843 private void handlePlayTone(int slotId) {
1844 TextMessage toneMsg = mStkContext[slotId].mCurrentCmd.geTextMessage();
1845
1846 boolean showUser = true;
1847 boolean displayDialog = true;
1848 Resources resource = Resources.getSystem();
1849 try {
1850 displayDialog = !resource.getBoolean(
1851 com.android.internal.R.bool.config_stkNoAlphaUsrCnf);
1852 } catch (NotFoundException e) {
1853 displayDialog = true;
1854 }
1855
1856 // As per the spec 3GPP TS 11.14, 6.4.5. Play Tone.
1857 // If there is no alpha identifier tlv present, UE may show the
1858 // user information. 'config_stkNoAlphaUsrCnf' value will decide
1859 // whether to show it or not.
1860 // If alpha identifier tlv is present and its data is null, play only tone
1861 // without showing user any information.
1862 // Alpha Id is Present, but the text data is null.
1863 if ((toneMsg.text != null ) && (toneMsg.text.equals(""))) {
1864 CatLog.d(this, "Alpha identifier data is null, play only tone");
1865 showUser = false;
1866 }
1867 // Alpha Id is not present AND we need to show info to the user.
1868 if (toneMsg.text == null && displayDialog) {
1869 CatLog.d(this, "toneMsg.text " + toneMsg.text
1870 + " Starting ToneDialog activity with default message.");
1871 toneMsg.text = getResources().getString(R.string.default_tone_dialog_msg);
1872 showUser = true;
1873 }
1874 // Dont show user info, if config setting is true.
1875 if (toneMsg.text == null && !displayDialog) {
1876 CatLog.d(this, "config value stkNoAlphaUsrCnf is true");
1877 showUser = false;
1878 }
1879
1880 CatLog.d(this, "toneMsg.text: " + toneMsg.text + "showUser: " +showUser +
1881 "displayDialog: " +displayDialog);
1882 playTone(showUser, slotId);
1883 }
1884
1885 private void playTone(boolean showUserInfo, int slotId) {
1886 // Start playing tone and vibration
1887 ToneSettings settings = mStkContext[slotId].mCurrentCmd.getToneSettings();
1888 if (null == settings) {
1889 CatLog.d(this, "null settings, not playing tone.");
1890 return;
1891 }
1892
1893 mVibrator = (Vibrator)getSystemService(VIBRATOR_SERVICE);
1894 mTonePlayer = new TonePlayer();
1895 mTonePlayer.play(settings.tone);
1896 int timeout = StkApp.calculateDurationInMilis(settings.duration);
1897 if (timeout == 0) {
1898 timeout = StkApp.TONE_DEFAULT_TIMEOUT;
1899 }
1900
1901 Message msg = mServiceHandler.obtainMessage();
1902 msg.arg1 = OP_STOP_TONE;
1903 msg.arg2 = slotId;
1904 msg.obj = (Integer)(showUserInfo ? 1 : 0);
1905 msg.what = STOP_TONE_WHAT;
1906 mServiceHandler.sendMessageDelayed(msg, timeout);
1907 if (settings.vibrate) {
1908 mVibrator.vibrate(timeout);
1909 }
1910
1911 // Start Tone dialog Activity to show user the information.
1912 if (showUserInfo) {
1913 Intent newIntent = new Intent(sInstance, ToneDialog.class);
1914 String uriString = STK_TONE_URI + slotId;
1915 Uri uriData = Uri.parse(uriString);
1916 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1917 | Intent.FLAG_ACTIVITY_NO_HISTORY
1918 | Intent.FLAG_ACTIVITY_SINGLE_TOP
1919 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
1920 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1921 newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
1922 newIntent.putExtra(SLOT_ID, slotId);
1923 newIntent.setData(uriData);
1924 startActivity(newIntent);
1925 }
1926 }
1927
1928 private void finishToneDialogActivity() {
1929 Intent finishIntent = new Intent(FINISH_TONE_ACTIVITY_ACTION);
1930 sendBroadcast(finishIntent);
1931 }
1932
1933 private void handleStopTone(Message msg, int slotId) {
1934 int resId = 0;
1935
1936 // Stop the play tone in following cases:
1937 // 1.OP_STOP_TONE: play tone timer expires.
1938 // 2.STOP_TONE_USER: user pressed the back key.
1939 if (msg.arg1 == OP_STOP_TONE) {
1940 resId = RES_ID_DONE;
1941 // Dismiss Tone dialog, after finishing off playing the tone.
1942 int finishActivity = (Integer) msg.obj;
1943 if (finishActivity == 1) finishToneDialogActivity();
1944 } else if (msg.arg1 == OP_STOP_TONE_USER) {
1945 resId = RES_ID_END_SESSION;
1946 }
1947
1948 sendResponse(resId, slotId, true);
1949 mServiceHandler.removeMessages(STOP_TONE_WHAT);
1950 if (mTonePlayer != null) {
1951 mTonePlayer.stop();
1952 mTonePlayer.release();
1953 mTonePlayer = null;
1954 }
1955 if (mVibrator != null) {
1956 mVibrator.cancel();
1957 mVibrator = null;
1958 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001959 }
1960
Takanori Nakano49b12722016-02-16 14:34:14 +09001961 private void launchOpenChannelDialog(final int slotId) {
Wink Savillee68857d2014-10-17 15:23:05 -07001962 TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001963 if (msg == null) {
Wink Savillee68857d2014-10-17 15:23:05 -07001964 CatLog.d(LOG_TAG, "msg is null, return here");
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001965 return;
1966 }
1967
1968 msg.title = getResources().getString(R.string.stk_dialog_title);
1969 if (msg.text == null) {
1970 msg.text = getResources().getString(R.string.default_open_channel_msg);
1971 }
1972
1973 final AlertDialog dialog = new AlertDialog.Builder(mContext)
1974 .setIconAttribute(android.R.attr.alertDialogIcon)
1975 .setTitle(msg.title)
1976 .setMessage(msg.text)
1977 .setCancelable(false)
1978 .setPositiveButton(getResources().getString(R.string.stk_dialog_accept),
1979 new DialogInterface.OnClickListener() {
1980 public void onClick(DialogInterface dialog, int which) {
1981 Bundle args = new Bundle();
1982 args.putInt(RES_ID, RES_ID_CHOICE);
1983 args.putInt(CHOICE, YES);
1984 Message message = mServiceHandler.obtainMessage();
1985 message.arg1 = OP_RESPONSE;
Takanori Nakano49b12722016-02-16 14:34:14 +09001986 message.arg2 = slotId;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001987 message.obj = args;
1988 mServiceHandler.sendMessage(message);
1989 }
1990 })
1991 .setNegativeButton(getResources().getString(R.string.stk_dialog_reject),
1992 new DialogInterface.OnClickListener() {
1993 public void onClick(DialogInterface dialog, int which) {
1994 Bundle args = new Bundle();
1995 args.putInt(RES_ID, RES_ID_CHOICE);
1996 args.putInt(CHOICE, NO);
1997 Message message = mServiceHandler.obtainMessage();
1998 message.arg1 = OP_RESPONSE;
Takanori Nakano49b12722016-02-16 14:34:14 +09001999 message.arg2 = slotId;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05002000 message.obj = args;
2001 mServiceHandler.sendMessage(message);
2002 }
2003 })
2004 .create();
2005
2006 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
2007 if (!mContext.getResources().getBoolean(
2008 com.android.internal.R.bool.config_sf_slowBlur)) {
2009 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
2010 }
2011
2012 dialog.show();
2013 }
2014
Wink Savillee68857d2014-10-17 15:23:05 -07002015 private void launchTransientEventMessage(int slotId) {
2016 TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05002017 if (msg == null) {
Wink Savillee68857d2014-10-17 15:23:05 -07002018 CatLog.d(LOG_TAG, "msg is null, return here");
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05002019 return;
2020 }
2021
2022 msg.title = getResources().getString(R.string.stk_dialog_title);
2023
2024 final AlertDialog dialog = new AlertDialog.Builder(mContext)
2025 .setIconAttribute(android.R.attr.alertDialogIcon)
2026 .setTitle(msg.title)
2027 .setMessage(msg.text)
2028 .setCancelable(false)
2029 .setPositiveButton(getResources().getString(android.R.string.ok),
2030 new DialogInterface.OnClickListener() {
2031 public void onClick(DialogInterface dialog, int which) {
2032 }
2033 })
2034 .create();
2035
2036 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
2037 if (!mContext.getResources().getBoolean(
2038 com.android.internal.R.bool.config_sf_slowBlur)) {
2039 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
2040 }
2041
2042 dialog.show();
2043 }
2044
Wink Savillee68857d2014-10-17 15:23:05 -07002045 private int getNotificationId(int slotId) {
2046 int notifyId = STK_NOTIFICATION_ID;
2047 if (slotId >= 0 && slotId < mSimCount) {
2048 notifyId += slotId;
2049 } else {
2050 CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
2051 }
2052 CatLog.d(LOG_TAG, "getNotificationId, slotId: " + slotId + ", notifyId: " + notifyId);
2053 return notifyId;
2054 }
2055
2056 private String getItemName(int itemId, int slotId) {
2057 Menu menu = mStkContext[slotId].mCurrentCmd.getMenu();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002058 if (menu == null) {
2059 return null;
2060 }
2061 for (Item item : menu.items) {
2062 if (item.id == itemId) {
2063 return item.text;
2064 }
2065 }
2066 return null;
2067 }
2068
Wink Savillee68857d2014-10-17 15:23:05 -07002069 private boolean removeMenu(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002070 try {
Wink Savillee68857d2014-10-17 15:23:05 -07002071 if (mStkContext[slotId].mCurrentMenu.items.size() == 1 &&
2072 mStkContext[slotId].mCurrentMenu.items.get(0) == null) {
2073 mStkContext[slotId].mSetupMenuState = STATE_NOT_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002074 return true;
2075 }
2076 } catch (NullPointerException e) {
Wink Savillee68857d2014-10-17 15:23:05 -07002077 CatLog.d(LOG_TAG, "Unable to get Menu's items size");
2078 mStkContext[slotId].mSetupMenuState = STATE_NOT_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002079 return true;
2080 }
Wink Savillee68857d2014-10-17 15:23:05 -07002081 mStkContext[slotId].mSetupMenuState = STATE_EXIST;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002082 return false;
2083 }
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +05302084
Wink Savillee68857d2014-10-17 15:23:05 -07002085 StkContext getStkContext(int slotId) {
2086 if (slotId >= 0 && slotId < mSimCount) {
2087 return mStkContext[slotId];
2088 } else {
2089 CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
2090 return null;
2091 }
2092 }
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +05302093
2094 private void handleAlphaNotify(Bundle args) {
2095 String alphaString = args.getString(AppInterface.ALPHA_STRING);
2096
2097 CatLog.d(this, "Alpha string received from card: " + alphaString);
2098 Toast toast = Toast.makeText(sInstance, alphaString, Toast.LENGTH_LONG);
2099 toast.setGravity(Gravity.TOP, 0, 0);
2100 toast.show();
2101 }
Srikanth Chintalaba103002015-11-30 10:49:52 -08002102
2103 private boolean isUrlAvailableToLaunchBrowser(BrowserSettings settings) {
2104 String url = SystemProperties.get(STK_BROWSER_DEFAULT_URL_SYSPROP, "");
2105 if (url == "" && settings.url == null) {
2106 return false;
2107 }
2108 return true;
2109 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002110}