blob: 526fb74a9ebac2d924c128dd0c15b593dedf8494 [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
Peter Wangc94b8e62019-12-30 17:09:10 -080019import static com.android.internal.telephony.cat.CatCmdMessage.SetupEventListConstants.IDLE_SCREEN_AVAILABLE_EVENT;
20import static com.android.internal.telephony.cat.CatCmdMessage.SetupEventListConstants.LANGUAGE_SELECTION_EVENT;
21import static com.android.internal.telephony.cat.CatCmdMessage.SetupEventListConstants.USER_ACTIVITY_EVENT;
feizhang5fd5c6f2021-06-30 13:59:02 +080022//add by qingyang.yi 2016.6.21 PR:1137553 add for Browser termination EVENT
23import static com.android.internal.telephony.cat.CatCmdMessage.SetupEventListConstants.BROWSER_TERMINATION_EVENT;
24//add end by qingyang.yi
Peter Wangc94b8e62019-12-30 17:09:10 -080025import android.app.Activity;
Preeti Ahuja95919342013-10-01 18:18:55 -070026import android.app.ActivityManager;
27import android.app.ActivityManager.RunningTaskInfo;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -050028import android.app.AlertDialog;
Hall Liu9d5d5ee2020-10-06 14:15:40 -070029import android.app.HomeVisibilityListener;
Yuta Uife965802017-11-07 20:12:37 +090030import android.app.KeyguardManager;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080031import android.app.Notification;
fionaxu2c91c752017-04-21 18:11:57 -070032import android.app.NotificationChannel;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080033import android.app.NotificationManager;
34import android.app.PendingIntent;
35import android.app.Service;
Yuta Uife965802017-11-07 20:12:37 +090036import android.content.BroadcastReceiver;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080037import android.content.Context;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -050038import android.content.DialogInterface;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080039import android.content.Intent;
Peter Wangc94b8e62019-12-30 17:09:10 -080040import android.content.IntentFilter;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +090041import android.content.pm.PackageManager;
42import android.content.pm.ResolveInfo;
Srikanth Chintala89aa6602014-03-14 16:26:57 +053043import android.content.res.Resources;
44import android.content.res.Resources.NotFoundException;
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +010045import android.graphics.Bitmap;
46import android.graphics.BitmapFactory;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080047import android.net.Uri;
48import android.os.Bundle;
49import android.os.Handler;
50import android.os.IBinder;
51import android.os.Looper;
52import android.os.Message;
Takanori Nakanoc8054ba2016-08-15 19:18:16 +090053import android.os.Parcel;
Sooraj Sasindrana4160472016-10-12 16:28:25 -070054import android.os.PersistableBundle;
Preeti Ahuja560be362014-11-25 19:38:24 -080055import android.os.PowerManager;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +090056import android.os.RemoteException;
Preeti Ahujaa7cdca22013-10-01 18:20:56 -070057import android.os.SystemProperties;
Srikanth Chintala89aa6602014-03-14 16:26:57 +053058import android.os.Vibrator;
Preeti Ahuja95919342013-10-01 18:18:55 -070059import android.provider.Settings;
Sooraj Sasindrana4160472016-10-12 16:28:25 -070060import android.telephony.CarrierConfigManager;
Yoshiaki Naka30d5a812018-11-12 12:43:34 +090061import android.telephony.SubscriptionInfo;
Yoshiaki Naka90183132017-08-31 19:25:33 +090062import android.telephony.SubscriptionManager;
Peter Wangc94b8e62019-12-30 17:09:10 -080063import android.telephony.TelephonyFrameworkInitializer;
Wink Saville56469d52009-04-02 01:37:03 -070064import android.telephony.TelephonyManager;
Preeti Ahujaa7cdca22013-10-01 18:20:56 -070065import android.text.TextUtils;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080066import android.view.Gravity;
67import android.view.LayoutInflater;
68import android.view.View;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -050069import android.view.WindowManager;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080070import android.widget.ImageView;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080071import android.widget.TextView;
72import android.widget.Toast;
73
Peter Wang10da9292020-01-27 12:36:00 +080074import androidx.localbroadcastmanager.content.LocalBroadcastManager;
75
Peter Wangc94b8e62019-12-30 17:09:10 -080076import com.android.internal.telephony.GsmAlphabet;
Peter Wanga14d13d2020-01-15 14:13:51 -080077import com.android.internal.telephony.ITelephony;
Malcolm Chenf961b652019-10-24 19:53:48 -070078import com.android.internal.telephony.PhoneConfigurationManager;
Peter Wangc94b8e62019-12-30 17:09:10 -080079import com.android.internal.telephony.PhoneConstants;
Peter Wang10da9292020-01-27 12:36:00 +080080import com.android.internal.telephony.TelephonyIntents;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070081import com.android.internal.telephony.cat.AppInterface;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070082import com.android.internal.telephony.cat.CatCmdMessage;
83import com.android.internal.telephony.cat.CatCmdMessage.BrowserSettings;
Preeti Ahuja95919342013-10-01 18:18:55 -070084import com.android.internal.telephony.cat.CatCmdMessage.SetupEventListSettings;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070085import com.android.internal.telephony.cat.CatLog;
86import com.android.internal.telephony.cat.CatResponseMessage;
Peter Wangc94b8e62019-12-30 17:09:10 -080087import com.android.internal.telephony.cat.CatService;
88import com.android.internal.telephony.cat.Input;
89import com.android.internal.telephony.cat.Item;
90import com.android.internal.telephony.cat.Menu;
91import com.android.internal.telephony.cat.ResultCode;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070092import com.android.internal.telephony.cat.TextMessage;
Srikanth Chintala89aa6602014-03-14 16:26:57 +053093import com.android.internal.telephony.cat.ToneSettings;
Wink Saville94e982b2014-07-11 07:38:14 -070094import com.android.internal.telephony.uicc.IccRefreshResponse;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080095
96import java.util.LinkedList;
Wink Savillee68857d2014-10-17 15:23:05 -070097import java.util.List;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080098
99/**
100 * SIM toolkit application level service. Interacts with Telephopny messages,
101 * application's launch and user input from STK UI elements.
Wink Saville79085fc2009-06-09 10:27:23 -0700102 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800103 */
104public class StkAppService extends Service implements Runnable {
105
106 // members
Wink Savillee68857d2014-10-17 15:23:05 -0700107 protected class StkContext {
108 protected CatCmdMessage mMainCmd = null;
109 protected CatCmdMessage mCurrentCmd = null;
110 protected CatCmdMessage mCurrentMenuCmd = null;
111 protected Menu mCurrentMenu = null;
112 protected String lastSelectedItem = null;
113 protected boolean mMenuIsVisible = false;
114 protected boolean mIsInputPending = false;
115 protected boolean mIsMenuPending = false;
116 protected boolean mIsDialogPending = false;
Yuta Uife965802017-11-07 20:12:37 +0900117 protected boolean mNotificationOnKeyguard = false;
118 protected boolean mNoResponseFromUser = false;
Wink Savillee68857d2014-10-17 15:23:05 -0700119 protected boolean launchBrowser = false;
120 protected BrowserSettings mBrowserSettings = null;
121 protected LinkedList<DelayedCmd> mCmdsQ = null;
122 protected boolean mCmdInProgress = false;
123 protected int mStkServiceState = STATE_UNKNOWN;
Wink Savillee68857d2014-10-17 15:23:05 -0700124 protected int mMenuState = StkMenuActivity.STATE_INIT;
125 protected int mOpCode = -1;
126 private Activity mActivityInstance = null;
127 private Activity mDialogInstance = null;
Yoshiaki Naka90183132017-08-31 19:25:33 +0900128 private Activity mImmediateDialogInstance = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700129 private int mSlotId = 0;
Preeti Ahuja95919342013-10-01 18:18:55 -0700130 private SetupEventListSettings mSetupEventListSettings = null;
131 private boolean mClearSelectItem = false;
132 private boolean mDisplayTextDlgIsVisibile = false;
133 private CatCmdMessage mCurrentSetupEventCmd = null;
Preeti Ahuja560be362014-11-25 19:38:24 -0800134 private CatCmdMessage mIdleModeTextCmd = null;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +0900135 private boolean mIdleModeTextVisible = false;
Takanori Nakano43dacc02018-07-26 11:27:39 +0900136 // Determins whether the current session was initiated by user operation.
137 protected boolean mIsSessionFromUser = false;
Wink Savillee68857d2014-10-17 15:23:05 -0700138 final synchronized void setPendingActivityInstance(Activity act) {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +0900139 CatLog.d(LOG_TAG, "setPendingActivityInstance act : " + mSlotId + ", " + act);
Wink Savillee68857d2014-10-17 15:23:05 -0700140 callSetActivityInstMsg(OP_SET_ACT_INST, mSlotId, act);
141 }
142 final synchronized Activity getPendingActivityInstance() {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +0900143 CatLog.d(LOG_TAG, "getPendingActivityInstance act : " + mSlotId + ", " +
Wink Savillee68857d2014-10-17 15:23:05 -0700144 mActivityInstance);
145 return mActivityInstance;
146 }
147 final synchronized void setPendingDialogInstance(Activity act) {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +0900148 CatLog.d(LOG_TAG, "setPendingDialogInstance act : " + mSlotId + ", " + act);
Wink Savillee68857d2014-10-17 15:23:05 -0700149 callSetActivityInstMsg(OP_SET_DAL_INST, mSlotId, act);
150 }
151 final synchronized Activity getPendingDialogInstance() {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +0900152 CatLog.d(LOG_TAG, "getPendingDialogInstance act : " + mSlotId + ", " +
Wink Savillee68857d2014-10-17 15:23:05 -0700153 mDialogInstance);
154 return mDialogInstance;
155 }
Yoshiaki Naka90183132017-08-31 19:25:33 +0900156 final synchronized void setImmediateDialogInstance(Activity act) {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +0900157 CatLog.d(LOG_TAG, "setImmediateDialogInstance act : " + mSlotId + ", " + act);
Yoshiaki Naka90183132017-08-31 19:25:33 +0900158 callSetActivityInstMsg(OP_SET_IMMED_DAL_INST, mSlotId, act);
159 }
160 final synchronized Activity getImmediateDialogInstance() {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +0900161 CatLog.d(LOG_TAG, "getImmediateDialogInstance act : " + mSlotId + ", " +
Yoshiaki Naka90183132017-08-31 19:25:33 +0900162 mImmediateDialogInstance);
163 return mImmediateDialogInstance;
164 }
Wink Savillee68857d2014-10-17 15:23:05 -0700165 }
166
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800167 private volatile Looper mServiceLooper;
168 private volatile ServiceHandler mServiceHandler;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800169 private Context mContext = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800170 private NotificationManager mNotificationManager = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800171 static StkAppService sInstance = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700172 private AppInterface[] mStkService = null;
173 private StkContext[] mStkContext = null;
174 private int mSimCount = 0;
Hall Liu9d5d5ee2020-10-06 14:15:40 -0700175 private HomeVisibilityListener mHomeVisibilityListener = null;
Yoshiaki Naka0c2d2ba2017-11-17 21:51:55 +0900176 private BroadcastReceiver mLocaleChangeReceiver = null;
Srikanth Chintala89aa6602014-03-14 16:26:57 +0530177 private TonePlayer mTonePlayer = null;
178 private Vibrator mVibrator = null;
Yoshiaki Nakafb997252017-09-19 20:14:58 +0900179 private BroadcastReceiver mUserActivityReceiver = null;
Preeti Ahuja95919342013-10-01 18:18:55 -0700180
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800181 // Used for setting FLAG_ACTIVITY_NO_USER_ACTION when
182 // creating an intent.
183 private enum InitiatedByUserAction {
184 yes, // The action was started via a user initiated action
185 unknown, // Not known for sure if user initated the action
186 }
187
188 // constants
189 static final String OPCODE = "op";
190 static final String CMD_MSG = "cmd message";
191 static final String RES_ID = "response id";
192 static final String MENU_SELECTION = "menu selection";
193 static final String INPUT = "input";
194 static final String HELP = "help";
195 static final String CONFIRMATION = "confirm";
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500196 static final String CHOICE = "choice";
Wink Savillee68857d2014-10-17 15:23:05 -0700197 static final String SLOT_ID = "SLOT_ID";
198 static final String STK_CMD = "STK CMD";
199 static final String STK_DIALOG_URI = "stk://com.android.stk/dialog/";
200 static final String STK_MENU_URI = "stk://com.android.stk/menu/";
201 static final String STK_INPUT_URI = "stk://com.android.stk/input/";
202 static final String STK_TONE_URI = "stk://com.android.stk/tone/";
Srikanth Chintala89aa6602014-03-14 16:26:57 +0530203 static final String FINISH_TONE_ACTIVITY_ACTION =
204 "android.intent.action.stk.finish_activity";
Preeti Ahuja95919342013-10-01 18:18:55 -0700205
206 // These below constants are used for SETUP_EVENT_LIST
207 static final String SETUP_EVENT_TYPE = "event";
208 static final String SETUP_EVENT_CAUSE = "cause";
209
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800210 // operations ids for different service functionality.
211 static final int OP_CMD = 1;
212 static final int OP_RESPONSE = 2;
213 static final int OP_LAUNCH_APP = 3;
214 static final int OP_END_SESSION = 4;
215 static final int OP_BOOT_COMPLETED = 5;
216 private static final int OP_DELAYED_MSG = 6;
Wink Saville94e982b2014-07-11 07:38:14 -0700217 static final int OP_CARD_STATUS_CHANGED = 7;
Wink Savillee68857d2014-10-17 15:23:05 -0700218 static final int OP_SET_ACT_INST = 8;
219 static final int OP_SET_DAL_INST = 9;
Ryuto Sawada08c821c2016-08-08 18:29:02 +0900220 static final int OP_LOCALE_CHANGED = 10;
221 static final int OP_ALPHA_NOTIFY = 11;
222 static final int OP_IDLE_SCREEN = 12;
Yoshiaki Naka90183132017-08-31 19:25:33 +0900223 static final int OP_SET_IMMED_DAL_INST = 13;
Anna Suzukib1cee232019-02-21 12:52:27 +0900224 static final int OP_HOME_KEY_PRESSED = 14;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800225
Preeti Ahuja95919342013-10-01 18:18:55 -0700226 //Invalid SetupEvent
227 static final int INVALID_SETUP_EVENT = 0xFF;
228
Srikanth Chintala89aa6602014-03-14 16:26:57 +0530229 // Message id to signal stop tone due to play tone timeout.
230 private static final int OP_STOP_TONE = 16;
231
232 // Message id to signal stop tone on user keyback.
233 static final int OP_STOP_TONE_USER = 17;
234
Yoshiaki Nakafb997252017-09-19 20:14:58 +0900235 // Message id to send user activity event to card.
236 private static final int OP_USER_ACTIVITY = 20;
237
Malcolm Chenf961b652019-10-24 19:53:48 -0700238 // Message id that multi-SIM config has changed (ss <-> ds).
239 private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 21;
240
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800241 // Response ids
242 static final int RES_ID_MENU_SELECTION = 11;
243 static final int RES_ID_INPUT = 12;
244 static final int RES_ID_CONFIRM = 13;
245 static final int RES_ID_DONE = 14;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500246 static final int RES_ID_CHOICE = 15;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800247
248 static final int RES_ID_TIMEOUT = 20;
249 static final int RES_ID_BACKWARD = 21;
250 static final int RES_ID_END_SESSION = 22;
251 static final int RES_ID_EXIT = 23;
Srikanth Chintalaba103002015-11-30 10:49:52 -0800252 static final int RES_ID_ERROR = 24;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800253
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500254 static final int YES = 1;
255 static final int NO = 0;
256
Wink Savillee68857d2014-10-17 15:23:05 -0700257 static final int STATE_UNKNOWN = -1;
258 static final int STATE_NOT_EXIST = 0;
259 static final int STATE_EXIST = 1;
Wink Saville79085fc2009-06-09 10:27:23 -0700260
Yoshiaki Nakab80f8ce2019-04-25 14:36:03 +0900261 private static final Integer PLAY_TONE_ONLY = 0;
262 private static final Integer PLAY_TONE_WITH_DIALOG = 1;
263
Wink Savillee68857d2014-10-17 15:23:05 -0700264 private static final String PACKAGE_NAME = "com.android.stk";
265 private static final String STK_MENU_ACTIVITY_NAME = PACKAGE_NAME + ".StkMenuActivity";
266 private static final String STK_INPUT_ACTIVITY_NAME = PACKAGE_NAME + ".StkInputActivity";
267 private static final String STK_DIALOG_ACTIVITY_NAME = PACKAGE_NAME + ".StkDialogActivity";
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800268 // Notification id used to display Idle Mode text in NotificationManager.
269 private static final int STK_NOTIFICATION_ID = 333;
fionaxu2c91c752017-04-21 18:11:57 -0700270 // Notification channel containing all mobile service messages notifications.
271 private static final String STK_NOTIFICATION_CHANNEL_ID = "mobileServiceMessages";
272
Yoshiaki Naka3a980db2019-10-30 17:11:33 +0900273 private static final String LOG_TAG =
274 new Object(){}.getClass().getEnclosingClass().getSimpleName();
Wink Saville79085fc2009-06-09 10:27:23 -0700275
Takanori Nakano3776e2c2016-10-14 16:54:28 +0900276 static final String SESSION_ENDED = "session_ended";
277
Wink Saville79085fc2009-06-09 10:27:23 -0700278 // Inner class used for queuing telephony messages (proactive commands,
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800279 // session end) while the service is busy processing a previous message.
280 private class DelayedCmd {
281 // members
282 int id;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700283 CatCmdMessage msg;
Wink Savillee68857d2014-10-17 15:23:05 -0700284 int slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800285
Wink Savillee68857d2014-10-17 15:23:05 -0700286 DelayedCmd(int id, CatCmdMessage msg, int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800287 this.id = id;
288 this.msg = msg;
Wink Savillee68857d2014-10-17 15:23:05 -0700289 this.slotId = slotId;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800290 }
291 }
292
Preeti Ahujaa7cdca22013-10-01 18:20:56 -0700293 // system property to set the STK specific default url for launch browser proactive cmds
294 private static final String STK_BROWSER_DEFAULT_URL_SYSPROP = "persist.radio.stk.default_url";
295
Umashankar Godachic77445b2018-02-28 02:51:56 +0530296 // Description of the Icon that is being dispalyed in a Stk activity.
297 public static final String TEXT_DEFAULT_ICON = "Stk Default Icon";
298 public static final String TEXT_ICON_FROM_COMMAND="Stk Icon from Command";
feizhang5fd5c6f2021-06-30 13:59:02 +0800299 //add by qingyang.yi 2016.6.21 PR:1137553 add for Browser termination EVENT
300 static final int OP_BROWSER_TERMINATION = 32;
301 private static final String BROWSER_TERMINATE_ACTION = "com.stk.intent.action.browser_terminate_action";
302 private static final String BROWSER_TERMINATION_CAUSE = "browser_termination_cause";
303 //add end by qingyang.yi
Umashankar Godachic77445b2018-02-28 02:51:56 +0530304
Yuta Uife965802017-11-07 20:12:37 +0900305 private static final int NOTIFICATION_ON_KEYGUARD = 1;
306 private static final long[] VIBRATION_PATTERN = new long[] { 0, 350, 250, 350 };
307 private BroadcastReceiver mUserPresentReceiver = null;
308
Anna Suzukib1cee232019-02-21 12:52:27 +0900309 // The reason based on Intent.ACTION_CLOSE_SYSTEM_DIALOGS.
310 private static final String SYSTEM_DIALOG_REASON_KEY = "reason";
311 private static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
Jordan Liu79fa1022020-08-04 11:34:03 -0700312 private static final String SYSTEM_DIALOG_REASON_RECENTAPPS_KEY = "recentapps";
Anna Suzukib1cee232019-02-21 12:52:27 +0900313 private BroadcastReceiver mHomeKeyEventReceiver = null;
314
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800315 @Override
316 public void onCreate() {
Wink Savillee68857d2014-10-17 15:23:05 -0700317 CatLog.d(LOG_TAG, "onCreate()+");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800318 // Initialize members
Wink Savillee68857d2014-10-17 15:23:05 -0700319 int i = 0;
320 mContext = getBaseContext();
Malcolm Chenf961b652019-10-24 19:53:48 -0700321 mSimCount = TelephonyManager.from(mContext).getActiveModemCount();
322 int maxSimCount = TelephonyManager.from(mContext).getSupportedModemCount();
Wink Savillee68857d2014-10-17 15:23:05 -0700323 CatLog.d(LOG_TAG, "simCount: " + mSimCount);
Malcolm Chenf961b652019-10-24 19:53:48 -0700324 mStkService = new AppInterface[maxSimCount];
325 mStkContext = new StkContext[maxSimCount];
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +0900326
Wink Savillee68857d2014-10-17 15:23:05 -0700327 for (i = 0; i < mSimCount; i++) {
328 CatLog.d(LOG_TAG, "slotId: " + i);
Legler Wuaeefef52014-10-27 00:57:18 +0800329 mStkService[i] = CatService.getInstance(i);
Wink Savillee68857d2014-10-17 15:23:05 -0700330 mStkContext[i] = new StkContext();
331 mStkContext[i].mSlotId = i;
332 mStkContext[i].mCmdsQ = new LinkedList<DelayedCmd>();
333 }
334
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800335 Thread serviceThread = new Thread(null, this, "Stk App Service");
336 serviceThread.start();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800337 mNotificationManager = (NotificationManager) mContext
338 .getSystemService(Context.NOTIFICATION_SERVICE);
339 sInstance = this;
340 }
341
342 @Override
343 public void onStart(Intent intent, int startId) {
Wink Savillee68857d2014-10-17 15:23:05 -0700344 if (intent == null) {
345 CatLog.d(LOG_TAG, "StkAppService onStart intent is null so return");
Banavathu, Srinivas Naik87cda962012-07-17 15:32:44 +0530346 return;
347 }
348
Wink Savillee68857d2014-10-17 15:23:05 -0700349 Bundle args = intent.getExtras();
350 if (args == null) {
351 CatLog.d(LOG_TAG, "StkAppService onStart args is null so return");
352 return;
353 }
354
355 int op = args.getInt(OPCODE);
356 int slotId = 0;
357 int i = 0;
358 if (op != OP_BOOT_COMPLETED) {
359 slotId = args.getInt(SLOT_ID);
360 }
Cuihtlauac ALVARADObde7f032015-05-29 16:25:12 +0200361 CatLog.d(LOG_TAG, "onStart sim id: " + slotId + ", op: " + op + ", *****");
Wink Savillee68857d2014-10-17 15:23:05 -0700362 if ((slotId >= 0 && slotId < mSimCount) && mStkService[slotId] == null) {
Legler Wuaeefef52014-10-27 00:57:18 +0800363 mStkService[slotId] = CatService.getInstance(slotId);
Wink Savillee68857d2014-10-17 15:23:05 -0700364 if (mStkService[slotId] == null) {
365 CatLog.d(LOG_TAG, "mStkService is: " + mStkContext[slotId].mStkServiceState);
366 mStkContext[slotId].mStkServiceState = STATE_NOT_EXIST;
367 //Check other StkService state.
368 //If all StkServices are not available, stop itself and uninstall apk.
Yoshiaki Naka8b960fb2019-10-31 10:44:07 +0900369 for (i = 0; i < mSimCount; i++) {
Wink Savillee68857d2014-10-17 15:23:05 -0700370 if (i != slotId
Tsukasa Goto029332b2016-10-05 17:12:06 +0900371 && (mStkService[i] != null)
Wink Savillee68857d2014-10-17 15:23:05 -0700372 && (mStkContext[i].mStkServiceState == STATE_UNKNOWN
373 || mStkContext[i].mStkServiceState == STATE_EXIST)) {
374 break;
375 }
376 }
377 } else {
378 mStkContext[slotId].mStkServiceState = STATE_EXIST;
379 }
380 if (i == mSimCount) {
381 stopSelf();
Yoshiaki Naka835e3002020-05-11 18:15:12 +0900382 StkAppInstaller.uninstall(this);
Wink Savillee68857d2014-10-17 15:23:05 -0700383 return;
384 }
385 }
386
Banavathu, Srinivas Naik87cda962012-07-17 15:32:44 +0530387 waitForLooper();
John Wang62acae42009-10-08 11:20:23 -0700388
Yoshiaki Nakab80f8ce2019-04-25 14:36:03 +0900389 Message msg = mServiceHandler.obtainMessage(op, 0, slotId);
390 switch (op) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800391 case OP_CMD:
392 msg.obj = args.getParcelable(CMD_MSG);
393 break;
394 case OP_RESPONSE:
Wink Saville94e982b2014-07-11 07:38:14 -0700395 case OP_CARD_STATUS_CHANGED:
Preeti Ahuja95919342013-10-01 18:18:55 -0700396 case OP_LOCALE_CHANGED:
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +0530397 case OP_ALPHA_NOTIFY:
Preeti Ahuja560be362014-11-25 19:38:24 -0800398 case OP_IDLE_SCREEN:
feizhang5fd5c6f2021-06-30 13:59:02 +0800399 //add by qingyang.yi 2016.6.21 PR:1137553 add for Browser termination EVENT
400 case OP_BROWSER_TERMINATION:
401 //add end by qingyang.yi
Yoshiaki Nakab80f8ce2019-04-25 14:36:03 +0900402 case OP_STOP_TONE_USER:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800403 msg.obj = args;
404 /* falls through */
405 case OP_LAUNCH_APP:
406 case OP_END_SESSION:
407 case OP_BOOT_COMPLETED:
408 break;
409 default:
410 return;
411 }
412 mServiceHandler.sendMessage(msg);
413 }
414
415 @Override
416 public void onDestroy() {
Wink Savillee68857d2014-10-17 15:23:05 -0700417 CatLog.d(LOG_TAG, "onDestroy()");
Yoshiaki Nakafb997252017-09-19 20:14:58 +0900418 unregisterUserActivityReceiver();
Malcolm Chen549e21a2020-01-10 15:57:10 -0800419 unregisterHomeVisibilityObserver();
Yoshiaki Naka0c2d2ba2017-11-17 21:51:55 +0900420 unregisterLocaleChangeReceiver();
Anna Suzukib1cee232019-02-21 12:52:27 +0900421 unregisterHomeKeyEventReceiver();
Tsukasa Gotou54afbdd2016-01-07 16:30:20 +0900422 sInstance = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800423 waitForLooper();
Yoshiaki Nakaf70e3732020-01-24 18:57:22 +0900424 PhoneConfigurationManager.unregisterForMultiSimConfigChange(mServiceHandler);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800425 mServiceLooper.quit();
426 }
427
428 @Override
429 public IBinder onBind(Intent intent) {
430 return null;
431 }
432
433 public void run() {
434 Looper.prepare();
435
436 mServiceLooper = Looper.myLooper();
437 mServiceHandler = new ServiceHandler();
438
Yoshiaki Nakaf70e3732020-01-24 18:57:22 +0900439 PhoneConfigurationManager.registerForMultiSimConfigChange(mServiceHandler,
440 EVENT_MULTI_SIM_CONFIG_CHANGED, null);
441
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800442 Looper.loop();
443 }
444
445 /*
446 * Package api used by StkMenuActivity to indicate if its on the foreground.
447 */
Malcolm Chenf961b652019-10-24 19:53:48 -0700448 synchronized void indicateMenuVisibility(boolean visibility, int slotId) {
Wink Savillee68857d2014-10-17 15:23:05 -0700449 if (slotId >= 0 && slotId < mSimCount) {
450 mStkContext[slotId].mMenuIsVisible = visibility;
451 }
452 }
453
Preeti Ahuja95919342013-10-01 18:18:55 -0700454 /*
455 * Package api used by StkDialogActivity to indicate if its on the foreground.
456 */
Malcolm Chenf961b652019-10-24 19:53:48 -0700457 synchronized void setDisplayTextDlgVisibility(boolean visibility, int slotId) {
Preeti Ahuja95919342013-10-01 18:18:55 -0700458 if (slotId >= 0 && slotId < mSimCount) {
459 mStkContext[slotId].mDisplayTextDlgIsVisibile = visibility;
460 }
461 }
462
Malcolm Chenf961b652019-10-24 19:53:48 -0700463 synchronized boolean isInputPending(int slotId) {
Wink Savillee68857d2014-10-17 15:23:05 -0700464 if (slotId >= 0 && slotId < mSimCount) {
465 CatLog.d(LOG_TAG, "isInputFinishBySrv: " + mStkContext[slotId].mIsInputPending);
466 return mStkContext[slotId].mIsInputPending;
467 }
468 return false;
469 }
470
Malcolm Chenf961b652019-10-24 19:53:48 -0700471 synchronized boolean isMenuPending(int slotId) {
Wink Savillee68857d2014-10-17 15:23:05 -0700472 if (slotId >= 0 && slotId < mSimCount) {
473 CatLog.d(LOG_TAG, "isMenuPending: " + mStkContext[slotId].mIsMenuPending);
474 return mStkContext[slotId].mIsMenuPending;
475 }
476 return false;
477 }
478
Malcolm Chenf961b652019-10-24 19:53:48 -0700479 synchronized boolean isDialogPending(int slotId) {
Wink Savillee68857d2014-10-17 15:23:05 -0700480 if (slotId >= 0 && slotId < mSimCount) {
481 CatLog.d(LOG_TAG, "isDialogPending: " + mStkContext[slotId].mIsDialogPending);
482 return mStkContext[slotId].mIsDialogPending;
483 }
484 return false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800485 }
486
Malcolm Chenf961b652019-10-24 19:53:48 -0700487 synchronized boolean isMainMenuAvailable(int slotId) {
Takanori Nakano3776e2c2016-10-14 16:54:28 +0900488 if (slotId >= 0 && slotId < mSimCount) {
489 // The main menu can handle the next user operation if the previous session finished.
490 return (mStkContext[slotId].lastSelectedItem == null) ? true : false;
491 }
492 return false;
493 }
494
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800495 /*
496 * Package api used by StkMenuActivity to get its Menu parameter.
497 */
Malcolm Chenf961b652019-10-24 19:53:48 -0700498 synchronized Menu getMenu(int slotId) {
Wink Savillee68857d2014-10-17 15:23:05 -0700499 CatLog.d(LOG_TAG, "StkAppService, getMenu, sim id: " + slotId);
500 if (slotId >=0 && slotId < mSimCount) {
501 return mStkContext[slotId].mCurrentMenu;
502 } else {
503 return null;
504 }
505 }
506
507 /*
508 * Package api used by StkMenuActivity to get its Main Menu parameter.
509 */
Malcolm Chenf961b652019-10-24 19:53:48 -0700510 synchronized Menu getMainMenu(int slotId) {
Wink Savillee68857d2014-10-17 15:23:05 -0700511 CatLog.d(LOG_TAG, "StkAppService, getMainMenu, sim id: " + slotId);
w30234a08cffe2015-02-04 15:13:25 -0800512 if (slotId >=0 && slotId < mSimCount && (mStkContext[slotId].mMainCmd != null)) {
Takanori Nakanoc8054ba2016-08-15 19:18:16 +0900513 Menu menu = mStkContext[slotId].mMainCmd.getMenu();
Yoshiaki Naka835e3002020-05-11 18:15:12 +0900514 if (menu != null) {
Takanori Nakanoc8054ba2016-08-15 19:18:16 +0900515 // If alpha identifier or icon identifier with the self-explanatory qualifier is
516 // specified in SET-UP MENU command, it should be more prioritized than preset ones.
517 if (menu.title == null
518 && (menu.titleIcon == null || !menu.titleIconSelfExplanatory)) {
519 StkMenuConfig config = StkMenuConfig.getInstance(getApplicationContext());
520 String label = config.getLabel(slotId);
521 Bitmap icon = config.getIcon(slotId);
522 if (label != null || icon != null) {
523 Parcel parcel = Parcel.obtain();
524 menu.writeToParcel(parcel, 0);
525 parcel.setDataPosition(0);
526 menu = Menu.CREATOR.createFromParcel(parcel);
527 parcel.recycle();
528 menu.title = label;
529 menu.titleIcon = icon;
530 menu.titleIconSelfExplanatory = false;
531 }
532 }
533 }
534 return menu;
Wink Savillee68857d2014-10-17 15:23:05 -0700535 } else {
536 return null;
537 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800538 }
539
540 /*
541 * Package api used by UI Activities and Dialogs to communicate directly
542 * with the service to deliver state information and parameters.
543 */
544 static StkAppService getInstance() {
545 return sInstance;
546 }
547
548 private void waitForLooper() {
549 while (mServiceHandler == null) {
550 synchronized (this) {
551 try {
552 wait(100);
553 } catch (InterruptedException e) {
554 }
555 }
556 }
557 }
558
559 private final class ServiceHandler extends Handler {
560 @Override
561 public void handleMessage(Message msg) {
Wink Savillee68857d2014-10-17 15:23:05 -0700562 if(null == msg) {
563 CatLog.d(LOG_TAG, "ServiceHandler handleMessage msg is null");
564 return;
565 }
Yoshiaki Nakab80f8ce2019-04-25 14:36:03 +0900566 int opcode = msg.what;
Wink Savillee68857d2014-10-17 15:23:05 -0700567 int slotId = msg.arg2;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800568
Wink Savillee68857d2014-10-17 15:23:05 -0700569 CatLog.d(LOG_TAG, "handleMessage opcode[" + opcode + "], sim id[" + slotId + "]");
570 if (opcode == OP_CMD && msg.obj != null &&
571 ((CatCmdMessage)msg.obj).getCmdType()!= null) {
572 CatLog.d(LOG_TAG, "cmdName[" + ((CatCmdMessage)msg.obj).getCmdType().name() + "]");
573 }
Malcolm Chen7a9f2ad2019-11-06 11:07:09 -0800574 if (slotId >= mStkContext.length || mStkContext[slotId] == null) {
575 CatLog.d(LOG_TAG, "invalid slotId " + slotId);
576 return;
577 }
Malcolm Chen5e576402019-11-05 16:09:18 -0800578
Wink Savillee68857d2014-10-17 15:23:05 -0700579 mStkContext[slotId].mOpCode = opcode;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800580 switch (opcode) {
581 case OP_LAUNCH_APP:
Wink Savillee68857d2014-10-17 15:23:05 -0700582 if (mStkContext[slotId].mMainCmd == null) {
583 CatLog.d(LOG_TAG, "mMainCmd is null");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800584 // nothing todo when no SET UP MENU command didn't arrive.
585 return;
586 }
Wink Savillee68857d2014-10-17 15:23:05 -0700587 CatLog.d(LOG_TAG, "handleMessage OP_LAUNCH_APP - mCmdInProgress[" +
588 mStkContext[slotId].mCmdInProgress + "]");
589
590 //If there is a pending activity for the slot id,
591 //just finish it and create a new one to handle the pending command.
592 cleanUpInstanceStackBySlot(slotId);
593
Wink Savillee68857d2014-10-17 15:23:05 -0700594 CatLog.d(LOG_TAG, "Current cmd type: " +
595 mStkContext[slotId].mCurrentCmd.getCmdType());
596 //Restore the last command from stack by slot id.
597 restoreInstanceFromStackBySlot(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800598 break;
599 case OP_CMD:
Wink Savillee68857d2014-10-17 15:23:05 -0700600 CatLog.d(LOG_TAG, "[OP_CMD]");
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700601 CatCmdMessage cmdMsg = (CatCmdMessage) msg.obj;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800602 // There are two types of commands:
603 // 1. Interactive - user's response is required.
604 // 2. Informative - display a message, no interaction with the user.
605 //
Wink Saville79085fc2009-06-09 10:27:23 -0700606 // Informative commands can be handled immediately without any delay.
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800607 // Interactive commands can't override each other. So if a command
608 // is already in progress, we need to queue the next command until
609 // the user has responded or a timeout expired.
610 if (!isCmdInteractive(cmdMsg)) {
Wink Savillee68857d2014-10-17 15:23:05 -0700611 handleCmd(cmdMsg, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800612 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700613 if (!mStkContext[slotId].mCmdInProgress) {
614 mStkContext[slotId].mCmdInProgress = true;
615 handleCmd((CatCmdMessage) msg.obj, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800616 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700617 CatLog.d(LOG_TAG, "[Interactive][in progress]");
618 mStkContext[slotId].mCmdsQ.addLast(new DelayedCmd(OP_CMD,
619 (CatCmdMessage) msg.obj, slotId));
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800620 }
621 }
622 break;
623 case OP_RESPONSE:
Preeti Ahuja414bc412013-06-25 19:31:49 -0700624 handleCmdResponse((Bundle) msg.obj, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800625 // call delayed commands if needed.
Wink Savillee68857d2014-10-17 15:23:05 -0700626 if (mStkContext[slotId].mCmdsQ.size() != 0) {
627 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800628 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700629 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800630 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800631 break;
632 case OP_END_SESSION:
Wink Savillee68857d2014-10-17 15:23:05 -0700633 if (!mStkContext[slotId].mCmdInProgress) {
634 mStkContext[slotId].mCmdInProgress = true;
635 handleSessionEnd(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800636 } else {
Wink Savillee68857d2014-10-17 15:23:05 -0700637 mStkContext[slotId].mCmdsQ.addLast(
638 new DelayedCmd(OP_END_SESSION, null, slotId));
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800639 }
640 break;
641 case OP_BOOT_COMPLETED:
Wink Savillee68857d2014-10-17 15:23:05 -0700642 CatLog.d(LOG_TAG, " OP_BOOT_COMPLETED");
Yoshiaki Naka58e07652019-04-26 17:58:52 +0900643 uninstallIfUnnecessary();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800644 break;
645 case OP_DELAYED_MSG:
Wink Savillee68857d2014-10-17 15:23:05 -0700646 handleDelayedCmd(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800647 break;
Wink Saville94e982b2014-07-11 07:38:14 -0700648 case OP_CARD_STATUS_CHANGED:
Wink Savillee68857d2014-10-17 15:23:05 -0700649 CatLog.d(LOG_TAG, "Card/Icc Status change received");
650 handleCardStatusChangeAndIccRefresh((Bundle) msg.obj, slotId);
651 break;
652 case OP_SET_ACT_INST:
Yoshiaki Naka28d7a722017-10-24 17:32:16 +0900653 Activity act = (Activity) msg.obj;
654 if (mStkContext[slotId].mActivityInstance != act) {
Yoshiaki Naka03a79d92018-08-09 18:41:31 +0900655 CatLog.d(LOG_TAG, "Set pending activity instance - " + act);
Yoshiaki Naka28d7a722017-10-24 17:32:16 +0900656 Activity previous = mStkContext[slotId].mActivityInstance;
657 mStkContext[slotId].mActivityInstance = act;
Yoshiaki Naka03a79d92018-08-09 18:41:31 +0900658 // Finish the previous one if it was replaced with new one
659 // but it has not been finished yet somehow.
660 if (act != null && previous != null && !previous.isDestroyed()
661 && !previous.isFinishing()) {
Yoshiaki Naka28d7a722017-10-24 17:32:16 +0900662 CatLog.d(LOG_TAG, "Finish the previous pending activity - " + previous);
663 previous.finish();
664 }
Anna Suzuki35309b02019-02-15 16:24:59 +0900665 }
666 // Clear pending dialog instance if it has not been cleared yet.
667 Activity dialog = mStkContext[slotId].getPendingDialogInstance();
668 if (dialog != null && (dialog.isDestroyed() || dialog.isFinishing())) {
669 CatLog.d(LOG_TAG, "Clear pending dialog instance - " + dialog);
670 mStkContext[slotId].mDialogInstance = null;
Yoshiaki Naka28d7a722017-10-24 17:32:16 +0900671 }
Wink Savillee68857d2014-10-17 15:23:05 -0700672 break;
673 case OP_SET_DAL_INST:
Yoshiaki Naka90183132017-08-31 19:25:33 +0900674 Activity dal = (Activity) msg.obj;
Yoshiaki Nakaa1cea462018-08-09 20:33:36 +0900675 if (mStkContext[slotId].mDialogInstance != dal) {
676 CatLog.d(LOG_TAG, "Set pending dialog instance - " + dal);
677 mStkContext[slotId].mDialogInstance = dal;
678 }
Wink Savillee68857d2014-10-17 15:23:05 -0700679 break;
Yoshiaki Naka90183132017-08-31 19:25:33 +0900680 case OP_SET_IMMED_DAL_INST:
681 Activity immedDal = (Activity) msg.obj;
682 CatLog.d(LOG_TAG, "Set dialog instance for immediate response. " + immedDal);
683 mStkContext[slotId].mImmediateDialogInstance = immedDal;
684 break;
Preeti Ahuja95919342013-10-01 18:18:55 -0700685 case OP_LOCALE_CHANGED:
Yoshiaki Naka3a980db2019-10-30 17:11:33 +0900686 CatLog.d(LOG_TAG, "Locale Changed");
Yoshiaki Naka8b960fb2019-10-31 10:44:07 +0900687 for (int slot = 0; slot < mSimCount; slot++) {
Yuta Ui1481b172016-02-03 15:34:31 +0900688 checkForSetupEvent(LANGUAGE_SELECTION_EVENT, (Bundle) msg.obj, slot);
689 }
fionaxu805eb572017-05-02 10:57:30 -0700690 // rename all registered notification channels on locale change
691 createAllChannels();
Preeti Ahuja95919342013-10-01 18:18:55 -0700692 break;
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +0530693 case OP_ALPHA_NOTIFY:
694 handleAlphaNotify((Bundle) msg.obj);
695 break;
Preeti Ahuja560be362014-11-25 19:38:24 -0800696 case OP_IDLE_SCREEN:
697 for (int slot = 0; slot < mSimCount; slot++) {
698 if (mStkContext[slot] != null) {
699 handleIdleScreen(slot);
700 }
701 }
702 break;
Srikanth Chintala89aa6602014-03-14 16:26:57 +0530703 case OP_STOP_TONE_USER:
704 case OP_STOP_TONE:
Yoshiaki Naka3a980db2019-10-30 17:11:33 +0900705 CatLog.d(LOG_TAG, "Stop tone");
Srikanth Chintala89aa6602014-03-14 16:26:57 +0530706 handleStopTone(msg, slotId);
707 break;
Yoshiaki Nakafb997252017-09-19 20:14:58 +0900708 case OP_USER_ACTIVITY:
Yoshiaki Naka8b960fb2019-10-31 10:44:07 +0900709 for (int slot = 0; slot < mSimCount; slot++) {
Yoshiaki Nakafb997252017-09-19 20:14:58 +0900710 checkForSetupEvent(USER_ACTIVITY_EVENT, null, slot);
711 }
712 break;
feizhang5fd5c6f2021-06-30 13:59:02 +0800713 //add by qingyang.yi 2016.6.21 PR:1137553 add for Browser termination EVENT
714 case OP_BROWSER_TERMINATION:
715 CatLog.d(LOG_TAG, "Browser Closed");
716 checkForSetupEvent(BROWSER_TERMINATION_EVENT, (Bundle) msg.obj,slotId);
717 break;
718 //add end by qingyang.yi
Malcolm Chenf961b652019-10-24 19:53:48 -0700719 case EVENT_MULTI_SIM_CONFIG_CHANGED:
720 handleMultiSimConfigChanged();
721 break;
Anna Suzukib1cee232019-02-21 12:52:27 +0900722 case OP_HOME_KEY_PRESSED:
723 CatLog.d(LOG_TAG, "Process the home key pressed event");
724 for (int slot = 0; slot < mSimCount; slot++) {
725 if (mStkContext[slot] != null) {
726 handleHomeKeyPressed(slot);
727 }
728 }
729 break;
Wink Saville94e982b2014-07-11 07:38:14 -0700730 }
731 }
732
Wink Savillee68857d2014-10-17 15:23:05 -0700733 private void handleCardStatusChangeAndIccRefresh(Bundle args, int slotId) {
Wink Saville94e982b2014-07-11 07:38:14 -0700734 boolean cardStatus = args.getBoolean(AppInterface.CARD_STATUS);
735
Wink Savillee68857d2014-10-17 15:23:05 -0700736 CatLog.d(LOG_TAG, "CardStatus: " + cardStatus);
Wink Saville94e982b2014-07-11 07:38:14 -0700737 if (cardStatus == false) {
Wink Savillee68857d2014-10-17 15:23:05 -0700738 CatLog.d(LOG_TAG, "CARD is ABSENT");
Wink Saville94e982b2014-07-11 07:38:14 -0700739 // Uninstall STKAPP, Clear Idle text, Stop StkAppService
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +0900740 cancelIdleText(slotId);
Srikanth Chintala7c5a04c2016-09-22 19:05:01 +0530741 mStkContext[slotId].mCurrentMenu = null;
742 mStkContext[slotId].mMainCmd = null;
Umashankar Godachi39e21302017-11-07 12:26:40 +0530743 mStkService[slotId] = null;
Takanori Nakanob82c8752019-04-01 14:47:07 +0900744 // Stop the tone currently being played if the relevant SIM is removed or disabled.
745 if (mStkContext[slotId].mCurrentCmd != null
746 && mStkContext[slotId].mCurrentCmd.getCmdType().value()
747 == AppInterface.CommandType.PLAY_TONE.value()) {
748 terminateTone(slotId);
749 }
Yoshiaki Naka2d10bbb2019-05-09 15:35:21 +0900750 if (!uninstallIfUnnecessary()) {
751 addToMenuSystemOrUpdateLabel();
752 }
Wink Savillee68857d2014-10-17 15:23:05 -0700753 if (isAllOtherCardsAbsent(slotId)) {
754 CatLog.d(LOG_TAG, "All CARDs are ABSENT");
Wink Savillee68857d2014-10-17 15:23:05 -0700755 stopSelf();
756 }
Wink Saville94e982b2014-07-11 07:38:14 -0700757 } else {
758 IccRefreshResponse state = new IccRefreshResponse();
759 state.refreshResult = args.getInt(AppInterface.REFRESH_RESULT);
Umashankar Godachi40a72f72017-09-12 15:16:55 +0530760 state.aid = args.getString(AppInterface.AID);
Wink Saville94e982b2014-07-11 07:38:14 -0700761
Umashankar Godachi40a72f72017-09-12 15:16:55 +0530762 CatLog.d(LOG_TAG, "Icc Refresh Result: "+ state.refreshResult
763 + " aid: " + state.aid);
Wink Saville94e982b2014-07-11 07:38:14 -0700764 if ((state.refreshResult == IccRefreshResponse.REFRESH_RESULT_INIT) ||
765 (state.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET)) {
766 // Clear Idle Text
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +0900767 cancelIdleText(slotId);
Wink Saville94e982b2014-07-11 07:38:14 -0700768 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800769 }
770 }
771 }
Malcolm Chenf961b652019-10-24 19:53:48 -0700772
773 private synchronized void handleMultiSimConfigChanged() {
774 int oldSimCount = mSimCount;
775 mSimCount = TelephonyManager.from(mContext).getActiveModemCount();
776 for (int i = oldSimCount; i < mSimCount; i++) {
777 CatLog.d(LOG_TAG, "slotId: " + i);
778 mStkService[i] = CatService.getInstance(i);
779 mStkContext[i] = new StkContext();
780 mStkContext[i].mSlotId = i;
781 mStkContext[i].mCmdsQ = new LinkedList<DelayedCmd>();
782 }
783
784 for (int i = mSimCount; i < oldSimCount; i++) {
785 CatLog.d(LOG_TAG, "slotId: " + i);
786 if (mStkService[i] != null) {
787 mStkService[i].dispose();
788 mStkService[i] = null;
789 }
790 mStkContext[i] = null;
791 }
792 }
793
Wink Savillee68857d2014-10-17 15:23:05 -0700794 /*
795 * Check if all SIMs are absent except the id of slot equals "slotId".
796 */
797 private boolean isAllOtherCardsAbsent(int slotId) {
798 TelephonyManager mTm = (TelephonyManager) mContext.getSystemService(
799 Context.TELEPHONY_SERVICE);
800 int i = 0;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800801
Wink Savillee68857d2014-10-17 15:23:05 -0700802 for (i = 0; i < mSimCount; i++) {
803 if (i != slotId && mTm.hasIccCard(i)) {
804 break;
805 }
806 }
807 if (i == mSimCount) {
808 return true;
809 } else {
810 return false;
811 }
812 }
Preeti Ahuja95919342013-10-01 18:18:55 -0700813
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +0900814 /* package */ boolean isScreenIdle() {
815 ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
816 List<RunningTaskInfo> tasks = am.getRunningTasks(1);
817 if (tasks == null || tasks.isEmpty()) {
818 return false;
819 }
820
821 String top = tasks.get(0).topActivity.getPackageName();
822 if (top == null) {
823 return false;
824 }
825
826 // We can assume that the screen is idle if the home application is in the foreground.
827 final Intent intent = new Intent(Intent.ACTION_MAIN, null);
828 intent.addCategory(Intent.CATEGORY_HOME);
829
830 ResolveInfo info = getPackageManager().resolveActivity(intent,
831 PackageManager.MATCH_DEFAULT_ONLY);
832 if (info != null) {
833 if (top.equals(info.activityInfo.packageName)) {
834 return true;
835 }
836 }
837
838 return false;
Preeti Ahuja560be362014-11-25 19:38:24 -0800839 }
840
Anna Suzukib1cee232019-02-21 12:52:27 +0900841 private synchronized void startToObserveHomeKeyEvent(int slotId) {
842 if (mStkContext[slotId].mIsSessionFromUser || mHomeKeyEventReceiver != null) {
843 return;
844 }
845 mHomeKeyEventReceiver = new BroadcastReceiver() {
846 @Override public void onReceive(Context context, Intent intent) {
Jordan Liu79fa1022020-08-04 11:34:03 -0700847 final String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
848 // gesture-based launchers may interpret swipe-up as "recent apps" instead of
849 // "home" so we accept both here
850 if (SYSTEM_DIALOG_REASON_HOME_KEY.equals(reason)
851 || SYSTEM_DIALOG_REASON_RECENTAPPS_KEY.equals(reason)) {
Jordan Liu468951a2020-08-21 09:16:23 -0700852 Message message = mServiceHandler.obtainMessage(OP_HOME_KEY_PRESSED);
Anna Suzukib1cee232019-02-21 12:52:27 +0900853 mServiceHandler.sendMessage(message);
Takanori Nakano43dacc02018-07-26 11:27:39 +0900854 }
Anna Suzukib1cee232019-02-21 12:52:27 +0900855 }
856 };
857 CatLog.d(LOG_TAG, "Started to observe home key event");
858 registerReceiver(mHomeKeyEventReceiver,
859 new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
860 }
861
862 private synchronized void unregisterHomeKeyEventReceiver() {
863 if (mHomeKeyEventReceiver != null) {
864 CatLog.d(LOG_TAG, "Stopped to observe home key event");
865 unregisterReceiver(mHomeKeyEventReceiver);
866 mHomeKeyEventReceiver = null;
867 }
868 if (mServiceHandler != null) {
869 mServiceHandler.removeMessages(OP_HOME_KEY_PRESSED);
870 }
871 }
872
873 private void handleHomeKeyPressed(int slotId) {
874 // It might be hard for user to recognize that the dialog or screens belong to SIM Toolkit
875 // application if the current session was not initiated by user but by the SIM card,
876 // so it is recommended to send TERMINAL RESPONSE if user press the home key.
877 if (!mStkContext[slotId].mIsSessionFromUser) {
878 Activity dialog = mStkContext[slotId].getPendingDialogInstance();
879 Activity activity = mStkContext[slotId].getPendingActivityInstance();
880 if (dialog != null) {
881 dialog.finish();
882 mStkContext[slotId].mDialogInstance = null;
883 } else if (activity != null) {
884 activity.finish();
885 mStkContext[slotId].mActivityInstance = null;
Takanori Nakano43dacc02018-07-26 11:27:39 +0900886 }
887 }
888 }
Preeti Ahuja560be362014-11-25 19:38:24 -0800889
Takanori Nakano43dacc02018-07-26 11:27:39 +0900890 private void handleIdleScreen(int slotId) {
Preeti Ahuja560be362014-11-25 19:38:24 -0800891 // If the idle screen event is present in the list need to send the
892 // response to SIM.
Yoshiaki Naka3a980db2019-10-30 17:11:33 +0900893 CatLog.d(LOG_TAG, "Need to send IDLE SCREEN Available event to SIM");
Preeti Ahuja560be362014-11-25 19:38:24 -0800894 checkForSetupEvent(IDLE_SCREEN_AVAILABLE_EVENT, null, slotId);
895
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +0900896 if (mStkContext[slotId].mIdleModeTextCmd != null
897 && !mStkContext[slotId].mIdleModeTextVisible) {
898 launchIdleText(slotId);
Preeti Ahuja560be362014-11-25 19:38:24 -0800899 }
900 }
901
902 private void sendScreenBusyResponse(int slotId) {
903 if (mStkContext[slotId].mCurrentCmd == null) {
904 return;
905 }
906 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentCmd);
Yoshiaki Naka3a980db2019-10-30 17:11:33 +0900907 CatLog.d(LOG_TAG, "SCREEN_BUSY");
Preeti Ahuja560be362014-11-25 19:38:24 -0800908 resMsg.setResultCode(ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS);
909 mStkService[slotId].onCmdResponse(resMsg);
910 if (mStkContext[slotId].mCmdsQ.size() != 0) {
911 callDelayedMsg(slotId);
912 } else {
913 mStkContext[slotId].mCmdInProgress = false;
914 }
915 }
916
Takanori Nakano43dacc02018-07-26 11:27:39 +0900917 /**
918 * Sends TERMINAL RESPONSE or ENVELOPE
919 *
920 * @param args detailed parameters of the response
921 * @param slotId slot identifier
922 */
923 public void sendResponse(Bundle args, int slotId) {
Yoshiaki Nakab80f8ce2019-04-25 14:36:03 +0900924 Message msg = mServiceHandler.obtainMessage(OP_RESPONSE, 0, slotId, args);
Takanori Nakano43dacc02018-07-26 11:27:39 +0900925 mServiceHandler.sendMessage(msg);
926 }
927
Preeti Ahuja95919342013-10-01 18:18:55 -0700928 private void sendResponse(int resId, int slotId, boolean confirm) {
Preeti Ahuja95919342013-10-01 18:18:55 -0700929 Bundle args = new Bundle();
930 args.putInt(StkAppService.RES_ID, resId);
Preeti Ahuja95919342013-10-01 18:18:55 -0700931 args.putBoolean(StkAppService.CONFIRMATION, confirm);
Yoshiaki Nakab80f8ce2019-04-25 14:36:03 +0900932 sendResponse(args, slotId);
Preeti Ahuja95919342013-10-01 18:18:55 -0700933 }
934
Takanori Nakanob82c8752019-04-01 14:47:07 +0900935 private void terminateTone(int slotId) {
936 Message msg = new Message();
937 msg.what = OP_STOP_TONE;
938 msg.obj = mServiceHandler.hasMessages(OP_STOP_TONE, PLAY_TONE_WITH_DIALOG)
939 ? PLAY_TONE_WITH_DIALOG : PLAY_TONE_ONLY;
940 handleStopTone(msg, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800941 }
942
Alex Yakavenkad41f1d92010-07-12 14:13:13 -0700943 private boolean isCmdInteractive(CatCmdMessage cmd) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800944 switch (cmd.getCmdType()) {
945 case SEND_DTMF:
946 case SEND_SMS:
Yoshiaki.Naka7f74e022017-11-25 16:42:39 +0900947 case REFRESH:
Avinash Nallurie4718132017-10-18 16:20:49 -0700948 case RUN_AT:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800949 case SEND_SS:
950 case SEND_USSD:
951 case SET_UP_IDLE_MODE_TEXT:
952 case SET_UP_MENU:
Kazuhiro Ondo764167c2011-10-21 16:05:05 -0500953 case CLOSE_CHANNEL:
954 case RECEIVE_DATA:
955 case SEND_DATA:
Preeti Ahuja95919342013-10-01 18:18:55 -0700956 case SET_UP_EVENT_LIST:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800957 return false;
958 }
959
960 return true;
961 }
962
Wink Savillee68857d2014-10-17 15:23:05 -0700963 private void handleDelayedCmd(int slotId) {
964 CatLog.d(LOG_TAG, "handleDelayedCmd, slotId: " + slotId);
965 if (mStkContext[slotId].mCmdsQ.size() != 0) {
966 DelayedCmd cmd = mStkContext[slotId].mCmdsQ.poll();
967 if (cmd != null) {
968 CatLog.d(LOG_TAG, "handleDelayedCmd - queue size: " +
969 mStkContext[slotId].mCmdsQ.size() +
970 " id: " + cmd.id + "sim id: " + cmd.slotId);
971 switch (cmd.id) {
972 case OP_CMD:
973 handleCmd(cmd.msg, cmd.slotId);
974 break;
975 case OP_END_SESSION:
976 handleSessionEnd(cmd.slotId);
977 break;
978 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800979 }
980 }
981 }
982
Wink Savillee68857d2014-10-17 15:23:05 -0700983 private void callDelayedMsg(int slotId) {
Yoshiaki Nakab80f8ce2019-04-25 14:36:03 +0900984 Message msg = mServiceHandler.obtainMessage(OP_DELAYED_MSG, 0, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800985 mServiceHandler.sendMessage(msg);
986 }
987
Yoshiaki Nakab80f8ce2019-04-25 14:36:03 +0900988 private void callSetActivityInstMsg(int opcode, int slotId, Object obj) {
989 Message msg = mServiceHandler.obtainMessage(opcode, 0, slotId, obj);
Wink Savillee68857d2014-10-17 15:23:05 -0700990 mServiceHandler.sendMessage(msg);
991 }
992
993 private void handleSessionEnd(int slotId) {
Legler Wuaeefef52014-10-27 00:57:18 +0800994 // We should finish all pending activity if receiving END SESSION command.
995 cleanUpInstanceStackBySlot(slotId);
996
Wink Savillee68857d2014-10-17 15:23:05 -0700997 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
998 CatLog.d(LOG_TAG, "[handleSessionEnd] - mCurrentCmd changed to mMainCmd!.");
999 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mMainCmd;
1000 CatLog.d(LOG_TAG, "slotId: " + slotId + ", mMenuState: " +
1001 mStkContext[slotId].mMenuState);
1002
1003 mStkContext[slotId].mIsInputPending = false;
1004 mStkContext[slotId].mIsMenuPending = false;
1005 mStkContext[slotId].mIsDialogPending = false;
Yuta Uife965802017-11-07 20:12:37 +09001006 mStkContext[slotId].mNoResponseFromUser = false;
Wink Savillee68857d2014-10-17 15:23:05 -07001007
Wink Savillee68857d2014-10-17 15:23:05 -07001008 if (mStkContext[slotId].mMainCmd == null) {
1009 CatLog.d(LOG_TAG, "[handleSessionEnd][mMainCmd is null!]");
1010 }
1011 mStkContext[slotId].lastSelectedItem = null;
Takanori Nakano43dacc02018-07-26 11:27:39 +09001012 mStkContext[slotId].mIsSessionFromUser = false;
Wink Saville79085fc2009-06-09 10:27:23 -07001013 // In case of SET UP MENU command which removed the app, don't
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001014 // update the current menu member.
Wink Savillee68857d2014-10-17 15:23:05 -07001015 if (mStkContext[slotId].mCurrentMenu != null && mStkContext[slotId].mMainCmd != null) {
1016 mStkContext[slotId].mCurrentMenu = mStkContext[slotId].mMainCmd.getMenu();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001017 }
Wink Savillee68857d2014-10-17 15:23:05 -07001018 CatLog.d(LOG_TAG, "[handleSessionEnd][mMenuState]" + mStkContext[slotId].mMenuIsVisible);
Ryuto Sawada08c821c2016-08-08 18:29:02 +09001019
Wink Savillee68857d2014-10-17 15:23:05 -07001020 if (StkMenuActivity.STATE_SECONDARY == mStkContext[slotId].mMenuState) {
Ryuto Sawada08c821c2016-08-08 18:29:02 +09001021 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001022 }
Takanori Nakano3776e2c2016-10-14 16:54:28 +09001023
1024 // Send a local broadcast as a notice that this service handled the session end event.
1025 Intent intent = new Intent(SESSION_ENDED);
1026 intent.putExtra(SLOT_ID, slotId);
1027 LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
1028
Wink Savillee68857d2014-10-17 15:23:05 -07001029 if (mStkContext[slotId].mCmdsQ.size() != 0) {
1030 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001031 } else {
Wink Savillee68857d2014-10-17 15:23:05 -07001032 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001033 }
1034 // In case a launch browser command was just confirmed, launch that url.
Wink Savillee68857d2014-10-17 15:23:05 -07001035 if (mStkContext[slotId].launchBrowser) {
1036 mStkContext[slotId].launchBrowser = false;
1037 launchBrowser(mStkContext[slotId].mBrowserSettings);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001038 }
1039 }
1040
Preeti Ahuja560be362014-11-25 19:38:24 -08001041 // returns true if any Stk related activity already has focus on the screen
Yoshiaki Nakacec55b82017-10-20 15:53:43 +09001042 boolean isTopOfStack() {
pkanwareab12f32017-02-06 08:35:03 -08001043 ActivityManager mActivityManager = (ActivityManager) mContext
Preeti Ahuja560be362014-11-25 19:38:24 -08001044 .getSystemService(ACTIVITY_SERVICE);
pkanwareab12f32017-02-06 08:35:03 -08001045 String currentPackageName = null;
1046 List<RunningTaskInfo> tasks = mActivityManager.getRunningTasks(1);
1047 if (tasks == null || tasks.get(0).topActivity == null) {
1048 return false;
1049 }
1050 currentPackageName = tasks.get(0).topActivity.getPackageName();
Preeti Ahuja560be362014-11-25 19:38:24 -08001051 if (null != currentPackageName) {
1052 return currentPackageName.equals(PACKAGE_NAME);
1053 }
Preeti Ahuja560be362014-11-25 19:38:24 -08001054 return false;
1055 }
1056
Sooraj Sasindrana4160472016-10-12 16:28:25 -07001057 /**
1058 * Get the boolean config from carrier config manager.
1059 *
Yukiko Fujimura913c1432019-02-21 17:14:30 +09001060 * @param context the context to get carrier service
Sooraj Sasindrana4160472016-10-12 16:28:25 -07001061 * @param key config key defined in CarrierConfigManager
Yoshiaki Naka028bb092018-08-30 16:57:47 +09001062 * @param slotId slot ID.
Sooraj Sasindrana4160472016-10-12 16:28:25 -07001063 * @return boolean value of corresponding key.
1064 */
Yukiko Fujimura913c1432019-02-21 17:14:30 +09001065 /* package */ static boolean getBooleanCarrierConfig(Context context, String key, int slotId) {
1066 CarrierConfigManager ccm = (CarrierConfigManager) context.getSystemService(
1067 Context.CARRIER_CONFIG_SERVICE);
1068 SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
Yoshiaki Naka30d5a812018-11-12 12:43:34 +09001069 Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Sooraj Sasindrana4160472016-10-12 16:28:25 -07001070 PersistableBundle b = null;
Yoshiaki Naka30d5a812018-11-12 12:43:34 +09001071 if (ccm != null && sm != null) {
1072 SubscriptionInfo info = sm.getActiveSubscriptionInfoForSimSlotIndex(slotId);
1073 if (info != null) {
1074 b = ccm.getConfigForSubId(info.getSubscriptionId());
1075 }
Sooraj Sasindrana4160472016-10-12 16:28:25 -07001076 }
1077 if (b != null) {
1078 return b.getBoolean(key);
Sooraj Sasindrana4160472016-10-12 16:28:25 -07001079 }
Yoshiaki Naka028bb092018-08-30 16:57:47 +09001080 // Return static default defined in CarrierConfigManager.
1081 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
Sooraj Sasindrana4160472016-10-12 16:28:25 -07001082 }
1083
Yukiko Fujimura913c1432019-02-21 17:14:30 +09001084 private boolean getBooleanCarrierConfig(String key, int slotId) {
1085 return getBooleanCarrierConfig(this, key, slotId);
1086 }
1087
Wink Savillee68857d2014-10-17 15:23:05 -07001088 private void handleCmd(CatCmdMessage cmdMsg, int slotId) {
Preeti Ahuja95919342013-10-01 18:18:55 -07001089
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001090 if (cmdMsg == null) {
1091 return;
1092 }
1093 // save local reference for state tracking.
Wink Savillee68857d2014-10-17 15:23:05 -07001094 mStkContext[slotId].mCurrentCmd = cmdMsg;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001095 boolean waitForUsersResponse = true;
1096
Wink Savillee68857d2014-10-17 15:23:05 -07001097 mStkContext[slotId].mIsInputPending = false;
1098 mStkContext[slotId].mIsMenuPending = false;
1099 mStkContext[slotId].mIsDialogPending = false;
1100
1101 CatLog.d(LOG_TAG,"[handleCmd]" + cmdMsg.getCmdType().name());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001102 switch (cmdMsg.getCmdType()) {
1103 case DISPLAY_TEXT:
1104 TextMessage msg = cmdMsg.geTextMessage();
Jeevaka Badrappan854a25c2012-12-01 16:32:03 +02001105 waitForUsersResponse = msg.responseNeeded;
Preeti Ahuja560be362014-11-25 19:38:24 -08001106 //If we receive a low priority Display Text and the device is
1107 // not displaying any STK related activity and the screen is not idle
1108 // ( that is, device is in an interactive state), then send a screen busy
1109 // terminal response. Otherwise display the message. The existing
1110 // displayed message shall be updated with the new display text
1111 // proactive command (Refer to ETSI TS 102 384 section 27.22.4.1.4.4.2).
1112 if (!(msg.isHighPriority || mStkContext[slotId].mMenuIsVisible
1113 || mStkContext[slotId].mDisplayTextDlgIsVisibile || isTopOfStack())) {
1114 if(!isScreenIdle()) {
1115 CatLog.d(LOG_TAG, "Screen is not idle");
1116 sendScreenBusyResponse(slotId);
1117 } else {
1118 launchTextDialog(slotId);
1119 }
1120 } else {
1121 launchTextDialog(slotId);
1122 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001123 break;
1124 case SELECT_ITEM:
Wink Savillee68857d2014-10-17 15:23:05 -07001125 CatLog.d(LOG_TAG, "SELECT_ITEM +");
1126 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
1127 mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
1128 launchMenuActivity(cmdMsg.getMenu(), slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001129 break;
1130 case SET_UP_MENU:
Wink Savillee68857d2014-10-17 15:23:05 -07001131 mStkContext[slotId].mCmdInProgress = false;
1132 mStkContext[slotId].mMainCmd = mStkContext[slotId].mCurrentCmd;
1133 mStkContext[slotId].mCurrentMenuCmd = mStkContext[slotId].mCurrentCmd;
1134 mStkContext[slotId].mCurrentMenu = cmdMsg.getMenu();
1135 CatLog.d(LOG_TAG, "SET_UP_MENU [" + removeMenu(slotId) + "]");
1136
1137 if (removeMenu(slotId)) {
Wink Savillee68857d2014-10-17 15:23:05 -07001138 mStkContext[slotId].mCurrentMenu = null;
Preeti Ahuja95919342013-10-01 18:18:55 -07001139 mStkContext[slotId].mMainCmd = null;
Wink Savillee68857d2014-10-17 15:23:05 -07001140 //Check other setup menu state. If all setup menu are removed, uninstall apk.
Yoshiaki Naka58e07652019-04-26 17:58:52 +09001141 if (!uninstallIfUnnecessary()) {
Yoshiaki Naka835e3002020-05-11 18:15:12 +09001142 addToMenuSystemOrUpdateLabel();
Wink Savillee68857d2014-10-17 15:23:05 -07001143 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001144 } else {
Yoshiaki Naka835e3002020-05-11 18:15:12 +09001145 addToMenuSystemOrUpdateLabel();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001146 }
Wink Savillee68857d2014-10-17 15:23:05 -07001147 if (mStkContext[slotId].mMenuIsVisible) {
1148 launchMenuActivity(null, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001149 }
1150 break;
1151 case GET_INPUT:
1152 case GET_INKEY:
Wink Savillee68857d2014-10-17 15:23:05 -07001153 launchInputActivity(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001154 break;
1155 case SET_UP_IDLE_MODE_TEXT:
1156 waitForUsersResponse = false;
Preeti Ahuja560be362014-11-25 19:38:24 -08001157 mStkContext[slotId].mIdleModeTextCmd = mStkContext[slotId].mCurrentCmd;
1158 TextMessage idleModeText = mStkContext[slotId].mCurrentCmd.geTextMessage();
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001159 if (idleModeText == null || TextUtils.isEmpty(idleModeText.text)) {
1160 cancelIdleText(slotId);
Preeti Ahuja560be362014-11-25 19:38:24 -08001161 }
1162 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001163 if (mStkContext[slotId].mIdleModeTextCmd != null) {
1164 if (mStkContext[slotId].mIdleModeTextVisible || isScreenIdle()) {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09001165 CatLog.d(LOG_TAG, "set up idle mode");
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001166 launchIdleText(slotId);
1167 } else {
Malcolm Chen549e21a2020-01-10 15:57:10 -08001168 registerHomeVisibilityObserver();
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001169 }
Preeti Ahuja560be362014-11-25 19:38:24 -08001170 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001171 break;
1172 case SEND_DTMF:
1173 case SEND_SMS:
Avinash Nallurie4718132017-10-18 16:20:49 -07001174 case RUN_AT:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001175 case SEND_SS:
1176 case SEND_USSD:
Preeti Ahuja95919342013-10-01 18:18:55 -07001177 case GET_CHANNEL_STATUS:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001178 waitForUsersResponse = false;
Wink Savillee68857d2014-10-17 15:23:05 -07001179 launchEventMessage(slotId);
Umashankar Godachid3598a22018-03-01 02:20:28 +05301180 //Reset the mCurrentCmd to mMainCmd, to avoid wrong TR sent for
1181 //SEND_SMS/SS/USSD, when user launches STK app next time and do
1182 //a menu selection.
1183 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001184 break;
Preeti Ahuja809fc5d2013-04-12 18:54:54 +05301185 case REFRESH:
1186 waitForUsersResponse = false;
1187 launchEventMessage(slotId);
1188 // Idle mode text needs to be cleared for init or reset modes of refresh
1189 if (cmdMsg.isRefreshResetOrInit()) {
1190 mNotificationManager.cancel(getNotificationId(slotId));
1191 mStkContext[slotId].mIdleModeTextCmd = null;
1192 CatLog.d(this, "Clean idle mode text due to refresh");
1193 }
1194 break;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001195 case LAUNCH_BROWSER:
Ryuto Sawada0bdc7192016-04-18 12:10:56 +09001196 // The device setup process should not be interrupted by launching browser.
1197 if (Settings.Global.getInt(mContext.getContentResolver(),
1198 Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09001199 CatLog.d(LOG_TAG, "Not perform if the setup process has not been completed.");
Ryuto Sawada0bdc7192016-04-18 12:10:56 +09001200 sendScreenBusyResponse(slotId);
1201 break;
1202 }
Sooraj Sasindrana4160472016-10-12 16:28:25 -07001203
1204 /* Check if Carrier would not want to launch browser */
Yoshiaki Naka028bb092018-08-30 16:57:47 +09001205 if (getBooleanCarrierConfig(CarrierConfigManager.KEY_STK_DISABLE_LAUNCH_BROWSER_BOOL,
1206 slotId)) {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09001207 CatLog.d(LOG_TAG, "Browser is not launched as per carrier.");
Sooraj Sasindrana4160472016-10-12 16:28:25 -07001208 sendResponse(RES_ID_DONE, slotId, true);
1209 break;
1210 }
1211
Srikanth Chintalaba103002015-11-30 10:49:52 -08001212 mStkContext[slotId].mBrowserSettings =
1213 mStkContext[slotId].mCurrentCmd.getBrowserSettings();
1214 if (!isUrlAvailableToLaunchBrowser(mStkContext[slotId].mBrowserSettings)) {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09001215 CatLog.d(LOG_TAG, "Browser url property is not set - send error");
Srikanth Chintalaba103002015-11-30 10:49:52 -08001216 sendResponse(RES_ID_ERROR, slotId, true);
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07001217 } else {
Srikanth Chintalaba103002015-11-30 10:49:52 -08001218 TextMessage alphaId = mStkContext[slotId].mCurrentCmd.geTextMessage();
1219 if ((alphaId == null) || TextUtils.isEmpty(alphaId.text)) {
1220 // don't need user confirmation in this case
1221 // just launch the browser or spawn a new tab
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09001222 CatLog.d(LOG_TAG, "user confirmation is not currently needed.\n" +
Srikanth Chintalaba103002015-11-30 10:49:52 -08001223 "supressing confirmation dialogue and confirming silently...");
1224 mStkContext[slotId].launchBrowser = true;
1225 sendResponse(RES_ID_CONFIRM, slotId, true);
1226 } else {
1227 launchConfirmationDialog(alphaId, slotId);
1228 }
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07001229 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001230 break;
1231 case SET_UP_CALL:
Preeti Ahujadd240102013-08-30 17:25:06 -07001232 TextMessage mesg = mStkContext[slotId].mCurrentCmd.getCallSettings().confirmMsg;
1233 if((mesg != null) && (mesg.text == null || mesg.text.length() == 0)) {
1234 mesg.text = getResources().getString(R.string.default_setup_call_msg);
1235 }
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09001236 CatLog.d(LOG_TAG, "SET_UP_CALL mesg.text " + mesg.text);
Preeti Ahujadd240102013-08-30 17:25:06 -07001237 launchConfirmationDialog(mesg, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001238 break;
1239 case PLAY_TONE:
Srikanth Chintala89aa6602014-03-14 16:26:57 +05301240 handlePlayTone(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001241 break;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001242 case OPEN_CHANNEL:
Wink Savillee68857d2014-10-17 15:23:05 -07001243 launchOpenChannelDialog(slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001244 break;
1245 case CLOSE_CHANNEL:
1246 case RECEIVE_DATA:
1247 case SEND_DATA:
Wink Savillee68857d2014-10-17 15:23:05 -07001248 TextMessage m = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001249
1250 if ((m != null) && (m.text == null)) {
1251 switch(cmdMsg.getCmdType()) {
1252 case CLOSE_CHANNEL:
1253 m.text = getResources().getString(R.string.default_close_channel_msg);
1254 break;
1255 case RECEIVE_DATA:
1256 m.text = getResources().getString(R.string.default_receive_data_msg);
1257 break;
1258 case SEND_DATA:
1259 m.text = getResources().getString(R.string.default_send_data_msg);
1260 break;
1261 }
1262 }
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001263 /*
1264 * Display indication in the form of a toast to the user if required.
1265 */
Wink Savillee68857d2014-10-17 15:23:05 -07001266 launchEventMessage(slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001267 break;
Preeti Ahuja95919342013-10-01 18:18:55 -07001268 case SET_UP_EVENT_LIST:
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001269 replaceEventList(slotId);
Preeti Ahuja560be362014-11-25 19:38:24 -08001270 if (isScreenIdle()) {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09001271 CatLog.d(LOG_TAG," Check if IDLE_SCREEN_AVAILABLE_EVENT is present in List");
Preeti Ahuja560be362014-11-25 19:38:24 -08001272 checkForSetupEvent(IDLE_SCREEN_AVAILABLE_EVENT, null, slotId);
1273 }
Preeti Ahuja95919342013-10-01 18:18:55 -07001274 break;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001275 }
1276
1277 if (!waitForUsersResponse) {
Wink Savillee68857d2014-10-17 15:23:05 -07001278 if (mStkContext[slotId].mCmdsQ.size() != 0) {
1279 callDelayedMsg(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001280 } else {
Wink Savillee68857d2014-10-17 15:23:05 -07001281 mStkContext[slotId].mCmdInProgress = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001282 }
1283 }
1284 }
1285
Yoshiaki Naka835e3002020-05-11 18:15:12 +09001286 private void addToMenuSystemOrUpdateLabel() {
1287 String candidateLabel = null;
1288
1289 for (int slotId = 0; slotId < mSimCount; slotId++) {
1290 Menu menu = getMainMenu(slotId);
1291 if (menu != null) {
1292 if (!TextUtils.isEmpty(candidateLabel)) {
1293 if (!TextUtils.equals(menu.title, candidateLabel)) {
1294 // We should not display the alpha identifier of SET-UP MENU command
1295 // as the application label on the application launcher
1296 // if different alpha identifiers are provided by multiple SIMs.
1297 candidateLabel = null;
1298 break;
1299 }
1300 } else {
1301 if (TextUtils.isEmpty(menu.title)) {
1302 break;
1303 }
1304 candidateLabel = menu.title;
1305 }
1306 }
1307 }
1308
1309 StkAppInstaller.installOrUpdate(this, candidateLabel);
1310 }
1311
Takanori Nakano43dacc02018-07-26 11:27:39 +09001312 @SuppressWarnings("FallThrough")
Wink Savillee68857d2014-10-17 15:23:05 -07001313 private void handleCmdResponse(Bundle args, int slotId) {
1314 CatLog.d(LOG_TAG, "handleCmdResponse, sim id: " + slotId);
Anna Suzukib1cee232019-02-21 12:52:27 +09001315 unregisterHomeKeyEventReceiver();
Wink Savillee68857d2014-10-17 15:23:05 -07001316 if (mStkContext[slotId].mCurrentCmd == null) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001317 return;
1318 }
Wink Savillee68857d2014-10-17 15:23:05 -07001319
1320 if (mStkService[slotId] == null) {
Legler Wuaeefef52014-10-27 00:57:18 +08001321 mStkService[slotId] = CatService.getInstance(slotId);
Wink Savillee68857d2014-10-17 15:23:05 -07001322 if (mStkService[slotId] == null) {
Takanori Nakanoeeed5db2019-04-08 12:21:29 +09001323 // CatService is disposed when the relevant SIM is removed or disabled.
1324 // StkAppService can also be stopped when the absent state is notified,
1325 // so this situation can happen.
1326 CatLog.d(LOG_TAG, "No response is sent back to the missing CatService.");
1327 return;
Alex Yakavenkad8e2ecd2012-04-20 17:10:15 -07001328 }
1329 }
1330
Wink Savillee68857d2014-10-17 15:23:05 -07001331 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentCmd);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001332
1333 // set result code
1334 boolean helpRequired = args.getBoolean(HELP, false);
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001335 boolean confirmed = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001336
1337 switch(args.getInt(RES_ID)) {
1338 case RES_ID_MENU_SELECTION:
Wink Savillee68857d2014-10-17 15:23:05 -07001339 CatLog.d(LOG_TAG, "MENU_SELECTION=" + mStkContext[slotId].
1340 mCurrentMenuCmd.getCmdType());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001341 int menuSelection = args.getInt(MENU_SELECTION);
Wink Savillee68857d2014-10-17 15:23:05 -07001342 switch(mStkContext[slotId].mCurrentMenuCmd.getCmdType()) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001343 case SET_UP_MENU:
Takanori Nakano43dacc02018-07-26 11:27:39 +09001344 mStkContext[slotId].mIsSessionFromUser = true;
1345 // Fall through
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001346 case SELECT_ITEM:
Wink Savillee68857d2014-10-17 15:23:05 -07001347 mStkContext[slotId].lastSelectedItem = getItemName(menuSelection, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001348 if (helpRequired) {
1349 resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
1350 } else {
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301351 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1352 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001353 }
1354 resMsg.setMenuSelection(menuSelection);
1355 break;
1356 }
1357 break;
1358 case RES_ID_INPUT:
Wink Savillee68857d2014-10-17 15:23:05 -07001359 CatLog.d(LOG_TAG, "RES_ID_INPUT");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001360 String input = args.getString(INPUT);
Wink Savillee68857d2014-10-17 15:23:05 -07001361 if (input != null && (null != mStkContext[slotId].mCurrentCmd.geInput()) &&
1362 (mStkContext[slotId].mCurrentCmd.geInput().yesNo)) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001363 boolean yesNoSelection = input
1364 .equals(StkInputActivity.YES_STR_RESPONSE);
1365 resMsg.setYesNo(yesNoSelection);
1366 } else {
1367 if (helpRequired) {
1368 resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
1369 } else {
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301370 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1371 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001372 resMsg.setInput(input);
1373 }
1374 }
1375 break;
1376 case RES_ID_CONFIRM:
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09001377 CatLog.d(LOG_TAG, "RES_ID_CONFIRM");
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001378 confirmed = args.getBoolean(CONFIRMATION);
Wink Savillee68857d2014-10-17 15:23:05 -07001379 switch (mStkContext[slotId].mCurrentCmd.getCmdType()) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001380 case DISPLAY_TEXT:
Preeti Ahujaf33bf392013-09-28 19:11:31 +05301381 if (confirmed) {
1382 resMsg.setResultCode(mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ?
1383 ResultCode.PRFRMD_ICON_NOT_DISPLAYED : ResultCode.OK);
1384 } else {
1385 resMsg.setResultCode(ResultCode.UICC_SESSION_TERM_BY_USER);
1386 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001387 break;
1388 case LAUNCH_BROWSER:
1389 resMsg.setResultCode(confirmed ? ResultCode.OK
1390 : ResultCode.UICC_SESSION_TERM_BY_USER);
1391 if (confirmed) {
Wink Savillee68857d2014-10-17 15:23:05 -07001392 mStkContext[slotId].launchBrowser = true;
1393 mStkContext[slotId].mBrowserSettings =
1394 mStkContext[slotId].mCurrentCmd.getBrowserSettings();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001395 }
1396 break;
1397 case SET_UP_CALL:
1398 resMsg.setResultCode(ResultCode.OK);
1399 resMsg.setConfirmation(confirmed);
1400 if (confirmed) {
Wink Savillee68857d2014-10-17 15:23:05 -07001401 launchEventMessage(slotId,
1402 mStkContext[slotId].mCurrentCmd.getCallSettings().callMsg);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001403 }
1404 break;
1405 }
1406 break;
1407 case RES_ID_DONE:
1408 resMsg.setResultCode(ResultCode.OK);
1409 break;
1410 case RES_ID_BACKWARD:
Wink Savillee68857d2014-10-17 15:23:05 -07001411 CatLog.d(LOG_TAG, "RES_ID_BACKWARD");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001412 resMsg.setResultCode(ResultCode.BACKWARD_MOVE_BY_USER);
1413 break;
1414 case RES_ID_END_SESSION:
Wink Savillee68857d2014-10-17 15:23:05 -07001415 CatLog.d(LOG_TAG, "RES_ID_END_SESSION");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001416 resMsg.setResultCode(ResultCode.UICC_SESSION_TERM_BY_USER);
1417 break;
1418 case RES_ID_TIMEOUT:
Wink Savillee68857d2014-10-17 15:23:05 -07001419 CatLog.d(LOG_TAG, "RES_ID_TIMEOUT");
Naveen Kallad5176892009-11-30 12:45:29 -08001420 // GCF test-case 27.22.4.1.1 Expected Sequence 1.5 (DISPLAY TEXT,
1421 // Clear message after delay, successful) expects result code OK.
1422 // If the command qualifier specifies no user response is required
1423 // then send OK instead of NO_RESPONSE_FROM_USER
Wink Savillee68857d2014-10-17 15:23:05 -07001424 if ((mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1425 AppInterface.CommandType.DISPLAY_TEXT.value())
1426 && (mStkContext[slotId].mCurrentCmd.geTextMessage().userClear == false)) {
Naveen Kallad5176892009-11-30 12:45:29 -08001427 resMsg.setResultCode(ResultCode.OK);
1428 } else {
1429 resMsg.setResultCode(ResultCode.NO_RESPONSE_FROM_USER);
1430 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001431 break;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001432 case RES_ID_CHOICE:
1433 int choice = args.getInt(CHOICE);
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09001434 CatLog.d(LOG_TAG, "User Choice=" + choice);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001435 switch (choice) {
1436 case YES:
1437 resMsg.setResultCode(ResultCode.OK);
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001438 confirmed = true;
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001439 break;
1440 case NO:
1441 resMsg.setResultCode(ResultCode.USER_NOT_ACCEPT);
1442 break;
1443 }
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001444
Wink Savillee68857d2014-10-17 15:23:05 -07001445 if (mStkContext[slotId].mCurrentCmd.getCmdType().value() ==
1446 AppInterface.CommandType.OPEN_CHANNEL.value()) {
Siddartha Pothapragadacacf7b82012-04-16 19:42:38 -07001447 resMsg.setConfirmation(confirmed);
1448 }
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05001449 break;
Srikanth Chintalaba103002015-11-30 10:49:52 -08001450 case RES_ID_ERROR:
1451 CatLog.d(LOG_TAG, "RES_ID_ERROR");
1452 switch (mStkContext[slotId].mCurrentCmd.getCmdType()) {
1453 case LAUNCH_BROWSER:
1454 resMsg.setResultCode(ResultCode.LAUNCH_BROWSER_ERROR);
1455 break;
1456 }
1457 break;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001458 default:
Wink Savillee68857d2014-10-17 15:23:05 -07001459 CatLog.d(LOG_TAG, "Unknown result id");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001460 return;
1461 }
Wink Savillee68857d2014-10-17 15:23:05 -07001462
Yuta Uife965802017-11-07 20:12:37 +09001463 switch (args.getInt(RES_ID)) {
1464 case RES_ID_MENU_SELECTION:
1465 case RES_ID_INPUT:
1466 case RES_ID_CONFIRM:
1467 case RES_ID_CHOICE:
1468 case RES_ID_BACKWARD:
1469 case RES_ID_END_SESSION:
1470 mStkContext[slotId].mNoResponseFromUser = false;
1471 break;
1472 case RES_ID_TIMEOUT:
1473 cancelNotificationOnKeyguard(slotId);
1474 mStkContext[slotId].mNoResponseFromUser = true;
1475 break;
1476 default:
1477 // The other IDs cannot be used to judge if there is no response from user.
1478 break;
1479 }
1480
Wink Savillee68857d2014-10-17 15:23:05 -07001481 if (null != mStkContext[slotId].mCurrentCmd &&
1482 null != mStkContext[slotId].mCurrentCmd.getCmdType()) {
1483 CatLog.d(LOG_TAG, "handleCmdResponse- cmdName[" +
1484 mStkContext[slotId].mCurrentCmd.getCmdType().name() + "]");
1485 }
1486 mStkService[slotId].onCmdResponse(resMsg);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001487 }
1488
1489 /**
1490 * Returns 0 or FLAG_ACTIVITY_NO_USER_ACTION, 0 means the user initiated the action.
1491 *
1492 * @param userAction If the userAction is yes then we always return 0 otherwise
1493 * mMenuIsVisible is used to determine what to return. If mMenuIsVisible is true
1494 * then we are the foreground app and we'll return 0 as from our perspective a
1495 * user action did cause. If it's false than we aren't the foreground app and
1496 * FLAG_ACTIVITY_NO_USER_ACTION is returned.
Wink Saville79085fc2009-06-09 10:27:23 -07001497 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001498 * @return 0 or FLAG_ACTIVITY_NO_USER_ACTION
1499 */
Wink Savillee68857d2014-10-17 15:23:05 -07001500 private int getFlagActivityNoUserAction(InitiatedByUserAction userAction, int slotId) {
1501 return ((userAction == InitiatedByUserAction.yes) | mStkContext[slotId].mMenuIsVisible)
1502 ? 0 : Intent.FLAG_ACTIVITY_NO_USER_ACTION;
1503 }
1504 /**
1505 * This method is used for cleaning up pending instances in stack.
Takanori Nakano28ce8b62018-02-22 12:10:44 +09001506 * No terminal response will be sent for pending instances.
Wink Savillee68857d2014-10-17 15:23:05 -07001507 */
1508 private void cleanUpInstanceStackBySlot(int slotId) {
1509 Activity activity = mStkContext[slotId].getPendingActivityInstance();
1510 Activity dialog = mStkContext[slotId].getPendingDialogInstance();
1511 CatLog.d(LOG_TAG, "cleanUpInstanceStackBySlot slotId: " + slotId);
1512 if (activity != null) {
Takanori Nakano28ce8b62018-02-22 12:10:44 +09001513 if (mStkContext[slotId].mCurrentCmd != null) {
1514 CatLog.d(LOG_TAG, "current cmd type: " +
1515 mStkContext[slotId].mCurrentCmd.getCmdType());
1516 if (mStkContext[slotId].mCurrentCmd.getCmdType().value()
1517 == AppInterface.CommandType.GET_INPUT.value()
1518 || mStkContext[slotId].mCurrentCmd.getCmdType().value()
1519 == AppInterface.CommandType.GET_INKEY.value()) {
1520 mStkContext[slotId].mIsInputPending = true;
1521 } else if (mStkContext[slotId].mCurrentCmd.getCmdType().value()
1522 == AppInterface.CommandType.SET_UP_MENU.value()
1523 || mStkContext[slotId].mCurrentCmd.getCmdType().value()
1524 == AppInterface.CommandType.SELECT_ITEM.value()) {
1525 mStkContext[slotId].mIsMenuPending = true;
1526 }
Wink Savillee68857d2014-10-17 15:23:05 -07001527 }
1528 CatLog.d(LOG_TAG, "finish pending activity.");
1529 activity.finish();
1530 mStkContext[slotId].mActivityInstance = null;
1531 }
1532 if (dialog != null) {
1533 CatLog.d(LOG_TAG, "finish pending dialog.");
1534 mStkContext[slotId].mIsDialogPending = true;
1535 dialog.finish();
1536 mStkContext[slotId].mDialogInstance = null;
1537 }
1538 }
1539 /**
1540 * This method is used for restoring pending instances from stack.
1541 */
1542 private void restoreInstanceFromStackBySlot(int slotId) {
1543 AppInterface.CommandType cmdType = mStkContext[slotId].mCurrentCmd.getCmdType();
1544
1545 CatLog.d(LOG_TAG, "restoreInstanceFromStackBySlot cmdType : " + cmdType);
1546 switch(cmdType) {
1547 case GET_INPUT:
1548 case GET_INKEY:
1549 launchInputActivity(slotId);
1550 //Set mMenuIsVisible to true for showing main menu for
1551 //following session end command.
1552 mStkContext[slotId].mMenuIsVisible = true;
1553 break;
1554 case DISPLAY_TEXT:
1555 launchTextDialog(slotId);
1556 break;
1557 case LAUNCH_BROWSER:
1558 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.geTextMessage(),
1559 slotId);
1560 break;
1561 case OPEN_CHANNEL:
1562 launchOpenChannelDialog(slotId);
1563 break;
1564 case SET_UP_CALL:
1565 launchConfirmationDialog(mStkContext[slotId].mCurrentCmd.getCallSettings().
1566 confirmMsg, slotId);
1567 break;
1568 case SET_UP_MENU:
1569 case SELECT_ITEM:
1570 launchMenuActivity(null, slotId);
1571 break;
1572 default:
1573 break;
1574 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001575 }
1576
Yoshiaki Naka90183132017-08-31 19:25:33 +09001577 @Override
1578 public void startActivity(Intent intent) {
1579 int slotId = intent.getIntExtra(SLOT_ID, SubscriptionManager.INVALID_SIM_SLOT_INDEX);
1580 // Close the dialog displayed for DISPLAY TEXT command with an immediate response object
1581 // before new dialog is displayed.
1582 if (SubscriptionManager.isValidSlotIndex(slotId)) {
1583 Activity dialog = mStkContext[slotId].getImmediateDialogInstance();
1584 if (dialog != null) {
1585 CatLog.d(LOG_TAG, "finish dialog for immediate response.");
1586 dialog.finish();
1587 }
1588 }
1589 super.startActivity(intent);
1590 }
1591
Wink Savillee68857d2014-10-17 15:23:05 -07001592 private void launchMenuActivity(Menu menu, int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001593 Intent newIntent = new Intent(Intent.ACTION_VIEW);
Wink Savillee68857d2014-10-17 15:23:05 -07001594 String targetActivity = STK_MENU_ACTIVITY_NAME;
1595 String uriString = STK_MENU_URI + System.currentTimeMillis();
1596 //Set unique URI to create a new instance of activity for different slotId.
1597 Uri uriData = Uri.parse(uriString);
1598
1599 CatLog.d(LOG_TAG, "launchMenuActivity, slotId: " + slotId + " , " +
1600 uriData.toString() + " , " + mStkContext[slotId].mOpCode + ", "
1601 + mStkContext[slotId].mMenuState);
1602 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1603 int intentFlags = Intent.FLAG_ACTIVITY_NEW_TASK;
1604
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001605 if (menu == null) {
1606 // We assume this was initiated by the user pressing the tool kit icon
Wink Savillee68857d2014-10-17 15:23:05 -07001607 intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.yes, slotId);
Wink Savillee68857d2014-10-17 15:23:05 -07001608 //If the last pending menu is secondary menu, "STATE" should be "STATE_SECONDARY".
1609 //Otherwise, it should be "STATE_MAIN".
1610 if (mStkContext[slotId].mOpCode == OP_LAUNCH_APP &&
1611 mStkContext[slotId].mMenuState == StkMenuActivity.STATE_SECONDARY) {
1612 newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
1613 } else {
1614 newIntent.putExtra("STATE", StkMenuActivity.STATE_MAIN);
1615 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_MAIN;
1616 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001617 } else {
1618 // We don't know and we'll let getFlagActivityNoUserAction decide.
Wink Savillee68857d2014-10-17 15:23:05 -07001619 intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001620 newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
Wink Savillee68857d2014-10-17 15:23:05 -07001621 mStkContext[slotId].mMenuState = StkMenuActivity.STATE_SECONDARY;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001622 }
Anna Suzuki35309b02019-02-15 16:24:59 +09001623 if (mStkContext[slotId].mMenuState == StkMenuActivity.STATE_SECONDARY) {
Anna Suzukib1cee232019-02-21 12:52:27 +09001624 startToObserveHomeKeyEvent(slotId);
Anna Suzuki35309b02019-02-15 16:24:59 +09001625 }
Wink Savillee68857d2014-10-17 15:23:05 -07001626 newIntent.putExtra(SLOT_ID, slotId);
1627 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001628 newIntent.setFlags(intentFlags);
Yoshiaki Naka90183132017-08-31 19:25:33 +09001629 startActivity(newIntent);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001630 }
1631
Wink Savillee68857d2014-10-17 15:23:05 -07001632 private void launchInputActivity(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001633 Intent newIntent = new Intent(Intent.ACTION_VIEW);
Wink Savillee68857d2014-10-17 15:23:05 -07001634 String targetActivity = STK_INPUT_ACTIVITY_NAME;
1635 String uriString = STK_INPUT_URI + System.currentTimeMillis();
1636 //Set unique URI to create a new instance of activity for different slotId.
1637 Uri uriData = Uri.parse(uriString);
Yuta Uife965802017-11-07 20:12:37 +09001638 Input input = mStkContext[slotId].mCurrentCmd.geInput();
Wink Savillee68857d2014-10-17 15:23:05 -07001639
1640 CatLog.d(LOG_TAG, "launchInputActivity, slotId: " + slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001641 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
Wink Savillee68857d2014-10-17 15:23:05 -07001642 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1643 newIntent.setClassName(PACKAGE_NAME, targetActivity);
Yuta Uife965802017-11-07 20:12:37 +09001644 newIntent.putExtra("INPUT", input);
Wink Savillee68857d2014-10-17 15:23:05 -07001645 newIntent.putExtra(SLOT_ID, slotId);
1646 newIntent.setData(uriData);
Yuta Uife965802017-11-07 20:12:37 +09001647
1648 if (input != null) {
1649 notifyUserIfNecessary(slotId, input.text);
1650 }
Yoshiaki Naka90183132017-08-31 19:25:33 +09001651 startActivity(newIntent);
Anna Suzukib1cee232019-02-21 12:52:27 +09001652 startToObserveHomeKeyEvent(slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001653 }
1654
Wink Savillee68857d2014-10-17 15:23:05 -07001655 private void launchTextDialog(int slotId) {
1656 CatLog.d(LOG_TAG, "launchTextDialog, slotId: " + slotId);
1657 Intent newIntent = new Intent();
1658 String targetActivity = STK_DIALOG_ACTIVITY_NAME;
1659 int action = getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId);
1660 String uriString = STK_DIALOG_URI + System.currentTimeMillis();
1661 //Set unique URI to create a new instance of activity for different slotId.
1662 Uri uriData = Uri.parse(uriString);
Yuta Uife965802017-11-07 20:12:37 +09001663 TextMessage textMessage = mStkContext[slotId].mCurrentCmd.geTextMessage();
1664
1665 newIntent.setClassName(PACKAGE_NAME, targetActivity);
1666 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
Yuta Uife965802017-11-07 20:12:37 +09001667 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
1668 newIntent.setData(uriData);
1669 newIntent.putExtra("TEXT", textMessage);
1670 newIntent.putExtra(SLOT_ID, slotId);
1671
1672 if (textMessage != null) {
1673 notifyUserIfNecessary(slotId, textMessage.text);
1674 }
1675 startActivity(newIntent);
1676 // For display texts with immediate response, send the terminal response
1677 // immediately. responseNeeded will be false, if display text command has
1678 // the immediate response tlv.
1679 if (!mStkContext[slotId].mCurrentCmd.geTextMessage().responseNeeded) {
1680 sendResponse(RES_ID_CONFIRM, slotId, true);
Anna Suzuki35309b02019-02-15 16:24:59 +09001681 } else {
Anna Suzukib1cee232019-02-21 12:52:27 +09001682 startToObserveHomeKeyEvent(slotId);
Yuta Uife965802017-11-07 20:12:37 +09001683 }
1684 }
1685
1686 private void notifyUserIfNecessary(int slotId, String message) {
1687 createAllChannels();
1688
1689 if (mStkContext[slotId].mNoResponseFromUser) {
1690 // No response from user was observed in the current session.
1691 // Do nothing in that case in order to avoid turning on the screen again and again
1692 // when the card repeatedly sends the same command in its retry procedure.
1693 return;
1694 }
1695
1696 PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
1697
1698 if (((KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE)).isKeyguardLocked()) {
1699 // Display the notification on the keyguard screen
1700 // if user cannot see the message from the card right now because of it.
1701 // The notification can be dismissed if user removed the keyguard screen.
1702 launchNotificationOnKeyguard(slotId, message);
Wink Savillee68857d2014-10-17 15:23:05 -07001703 }
Yuta Uife965802017-11-07 20:12:37 +09001704
1705 // Turn on the screen.
1706 PowerManager.WakeLock wakelock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
1707 | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, LOG_TAG);
1708 wakelock.acquire();
1709 wakelock.release();
1710 }
1711
1712 private void launchNotificationOnKeyguard(int slotId, String message) {
1713 Notification.Builder builder = new Notification.Builder(this, STK_NOTIFICATION_CHANNEL_ID);
1714
1715 builder.setStyle(new Notification.BigTextStyle(builder).bigText(message));
1716 builder.setContentText(message);
1717
1718 Menu menu = getMainMenu(slotId);
Zhang Renjie717bb8d2021-08-20 17:38:24 +08001719 // add by T2M.zhangrenjie for FP4-2257 2021-08-20 begin
1720
1721 /*if (menu == null || TextUtils.isEmpty(menu.title)) {
Jordan Liu3bd92cd2020-08-12 11:49:48 -07001722 builder.setContentTitle("");
Yuta Uife965802017-11-07 20:12:37 +09001723 } else {
1724 builder.setContentTitle(menu.title);
Zhang Renjie717bb8d2021-08-20 17:38:24 +08001725 }*/
Zhang Renjiec8ecd5f2021-08-27 16:45:50 +08001726 Bundle extras = new Bundle();
1727 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, " ");
1728 builder.addExtras(extras);
Zhang Renjie717bb8d2021-08-20 17:38:24 +08001729 builder.setContentTitle("");
Zhang Renjiec8ecd5f2021-08-27 16:45:50 +08001730 // add by T2M.zhangrenjie for FP4-2257 2021-08-20 end
1731
Sooraj Sasindran2b44d5b2020-01-29 15:17:48 -08001732 builder.setSmallIcon(R.drawable.stat_notify_sim_toolkit);
Yuta Uife965802017-11-07 20:12:37 +09001733 builder.setOngoing(true);
1734 builder.setOnlyAlertOnce(true);
1735 builder.setColor(getResources().getColor(
1736 com.android.internal.R.color.system_notification_accent_color));
1737
1738 registerUserPresentReceiver();
1739 mNotificationManager.notify(getNotificationId(NOTIFICATION_ON_KEYGUARD, slotId),
1740 builder.build());
1741 mStkContext[slotId].mNotificationOnKeyguard = true;
1742 }
1743
1744 private void cancelNotificationOnKeyguard(int slotId) {
1745 mNotificationManager.cancel(getNotificationId(NOTIFICATION_ON_KEYGUARD, slotId));
1746 mStkContext[slotId].mNotificationOnKeyguard = false;
1747 unregisterUserPresentReceiver(slotId);
1748 }
1749
1750 private synchronized void registerUserPresentReceiver() {
1751 if (mUserPresentReceiver == null) {
1752 mUserPresentReceiver = new BroadcastReceiver() {
1753 @Override public void onReceive(Context context, Intent intent) {
1754 if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
1755 for (int slot = 0; slot < mSimCount; slot++) {
1756 cancelNotificationOnKeyguard(slot);
1757 }
1758 }
1759 }
1760 };
1761 registerReceiver(mUserPresentReceiver, new IntentFilter(Intent.ACTION_USER_PRESENT));
1762 }
1763 }
1764
1765 private synchronized void unregisterUserPresentReceiver(int slotId) {
1766 if (mUserPresentReceiver != null) {
Yoshiaki Naka8b960fb2019-10-31 10:44:07 +09001767 for (int slot = 0; slot < mSimCount; slot++) {
Yuta Uife965802017-11-07 20:12:37 +09001768 if (slot != slotId) {
1769 if (mStkContext[slot].mNotificationOnKeyguard) {
1770 // The broadcast receiver is still necessary for other SIM card.
1771 return;
1772 }
1773 }
1774 }
1775 unregisterReceiver(mUserPresentReceiver);
1776 mUserPresentReceiver = null;
1777 }
1778 }
1779
1780 private int getNotificationId(int notificationType, int slotId) {
1781 return getNotificationId(slotId) + (notificationType * mSimCount);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001782 }
1783
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001784 private void replaceEventList(int slotId) {
1785 if (mStkContext[slotId].mSetupEventListSettings != null) {
1786 for (int current : mStkContext[slotId].mSetupEventListSettings.eventList) {
1787 if (current != INVALID_SETUP_EVENT) {
1788 // Cancel the event notification if it is not listed in the new event list.
1789 if ((mStkContext[slotId].mCurrentCmd.getSetEventList() == null)
1790 || !findEvent(current, mStkContext[slotId].mCurrentCmd
1791 .getSetEventList().eventList)) {
1792 unregisterEvent(current, slotId);
1793 }
1794 }
1795 }
1796 }
1797 mStkContext[slotId].mSetupEventListSettings
1798 = mStkContext[slotId].mCurrentCmd.getSetEventList();
1799 mStkContext[slotId].mCurrentSetupEventCmd = mStkContext[slotId].mCurrentCmd;
1800 mStkContext[slotId].mCurrentCmd = mStkContext[slotId].mMainCmd;
1801 registerEvents(slotId);
1802 }
1803
1804 private boolean findEvent(int event, int[] eventList) {
1805 for (int content : eventList) {
1806 if (content == event) return true;
1807 }
1808 return false;
1809 }
1810
1811 private void unregisterEvent(int event, int slotId) {
Yoshiaki Naka8b960fb2019-10-31 10:44:07 +09001812 for (int slot = 0; slot < mSimCount; slot++) {
Yoshiaki Naka0c2d2ba2017-11-17 21:51:55 +09001813 if (slot != slotId) {
1814 if (mStkContext[slot].mSetupEventListSettings != null) {
1815 if (findEvent(event, mStkContext[slot].mSetupEventListSettings.eventList)) {
1816 // The specified event shall never be canceled
1817 // if there is any other SIM card which requests the event.
1818 return;
1819 }
1820 }
1821 }
1822 }
1823
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001824 switch (event) {
Yoshiaki Nakafb997252017-09-19 20:14:58 +09001825 case USER_ACTIVITY_EVENT:
1826 unregisterUserActivityReceiver();
1827 break;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001828 case IDLE_SCREEN_AVAILABLE_EVENT:
Malcolm Chen549e21a2020-01-10 15:57:10 -08001829 unregisterHomeVisibilityObserver(AppInterface.CommandType.SET_UP_EVENT_LIST, slotId);
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001830 break;
1831 case LANGUAGE_SELECTION_EVENT:
Yoshiaki Naka0c2d2ba2017-11-17 21:51:55 +09001832 unregisterLocaleChangeReceiver();
1833 break;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001834 default:
1835 break;
1836 }
1837 }
1838
1839 private void registerEvents(int slotId) {
1840 if (mStkContext[slotId].mSetupEventListSettings == null) {
1841 return;
1842 }
1843 for (int event : mStkContext[slotId].mSetupEventListSettings.eventList) {
1844 switch (event) {
Yoshiaki Nakafb997252017-09-19 20:14:58 +09001845 case USER_ACTIVITY_EVENT:
1846 registerUserActivityReceiver();
1847 break;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001848 case IDLE_SCREEN_AVAILABLE_EVENT:
Malcolm Chen549e21a2020-01-10 15:57:10 -08001849 registerHomeVisibilityObserver();
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001850 break;
1851 case LANGUAGE_SELECTION_EVENT:
Yoshiaki Naka0c2d2ba2017-11-17 21:51:55 +09001852 registerLocaleChangeReceiver();
1853 break;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001854 default:
1855 break;
1856 }
1857 }
1858 }
1859
Yoshiaki Nakafb997252017-09-19 20:14:58 +09001860 private synchronized void registerUserActivityReceiver() {
1861 if (mUserActivityReceiver == null) {
1862 mUserActivityReceiver = new BroadcastReceiver() {
1863 @Override public void onReceive(Context context, Intent intent) {
Peter Wang10da9292020-01-27 12:36:00 +08001864 if (TelephonyIntents.ACTION_USER_ACTIVITY_NOTIFICATION.equals(
Yoshiaki Nakafb997252017-09-19 20:14:58 +09001865 intent.getAction())) {
Yoshiaki Nakab80f8ce2019-04-25 14:36:03 +09001866 Message message = mServiceHandler.obtainMessage(OP_USER_ACTIVITY);
Yoshiaki Nakafb997252017-09-19 20:14:58 +09001867 mServiceHandler.sendMessage(message);
1868 unregisterUserActivityReceiver();
1869 }
1870 }
1871 };
1872 registerReceiver(mUserActivityReceiver, new IntentFilter(
Peter Wang10da9292020-01-27 12:36:00 +08001873 TelephonyIntents.ACTION_USER_ACTIVITY_NOTIFICATION));
Yoshiaki Nakafb997252017-09-19 20:14:58 +09001874 try {
Peter Wanga14d13d2020-01-15 14:13:51 -08001875 ITelephony telephony = ITelephony.Stub.asInterface(
Peter Wangc94b8e62019-12-30 17:09:10 -08001876 TelephonyFrameworkInitializer
1877 .getTelephonyServiceManager()
Peter Wanga14d13d2020-01-15 14:13:51 -08001878 .getTelephonyServiceRegisterer()
Peter Wangc94b8e62019-12-30 17:09:10 -08001879 .get());
Peter Wanga14d13d2020-01-15 14:13:51 -08001880 telephony.requestUserActivityNotification();
Yoshiaki Nakafb997252017-09-19 20:14:58 +09001881 } catch (RemoteException e) {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09001882 CatLog.e(LOG_TAG, "failed to init WindowManager:" + e);
Yoshiaki Nakafb997252017-09-19 20:14:58 +09001883 }
1884 }
1885 }
1886
1887 private synchronized void unregisterUserActivityReceiver() {
1888 if (mUserActivityReceiver != null) {
1889 unregisterReceiver(mUserActivityReceiver);
1890 mUserActivityReceiver = null;
1891 }
1892 }
1893
Malcolm Chen549e21a2020-01-10 15:57:10 -08001894 private synchronized void registerHomeVisibilityObserver() {
Hall Liu9d5d5ee2020-10-06 14:15:40 -07001895 if (mHomeVisibilityListener == null) {
1896 mHomeVisibilityListener = new HomeVisibilityListener() {
Malcolm Chen549e21a2020-01-10 15:57:10 -08001897 @Override
1898 public void onHomeVisibilityChanged(boolean isHomeActivityVisible) {
1899 if (isHomeActivityVisible) {
1900 Message message = mServiceHandler.obtainMessage(OP_IDLE_SCREEN);
1901 mServiceHandler.sendMessage(message);
1902 unregisterHomeVisibilityObserver();
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001903 }
Malcolm Chen549e21a2020-01-10 15:57:10 -08001904 }
1905 };
1906 ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
Hall Liu9d5d5ee2020-10-06 14:15:40 -07001907 am.addHomeVisibilityListener(Runnable::run, mHomeVisibilityListener);
Malcolm Chen549e21a2020-01-10 15:57:10 -08001908 CatLog.d(LOG_TAG, "Started to observe the foreground activity");
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001909 }
1910 }
1911
Malcolm Chen549e21a2020-01-10 15:57:10 -08001912 private void unregisterHomeVisibilityObserver(AppInterface.CommandType command, int slotId) {
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001913 // Check if there is any pending command which still needs the process observer
1914 // except for the current command and slot.
Yoshiaki Naka8b960fb2019-10-31 10:44:07 +09001915 for (int slot = 0; slot < mSimCount; slot++) {
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001916 if (command != AppInterface.CommandType.SET_UP_IDLE_MODE_TEXT || slot != slotId) {
1917 if (mStkContext[slot].mIdleModeTextCmd != null
1918 && !mStkContext[slot].mIdleModeTextVisible) {
1919 // Keep the process observer registered
1920 // as there is an idle mode text which has not been visible yet.
1921 return;
1922 }
1923 }
1924 if (command != AppInterface.CommandType.SET_UP_EVENT_LIST || slot != slotId) {
1925 if (mStkContext[slot].mSetupEventListSettings != null) {
1926 if (findEvent(IDLE_SCREEN_AVAILABLE_EVENT,
1927 mStkContext[slot].mSetupEventListSettings.eventList)) {
1928 // Keep the process observer registered
1929 // as there is a SIM card which still want IDLE SCREEN AVAILABLE event.
1930 return;
1931 }
1932 }
1933 }
1934 }
Malcolm Chen549e21a2020-01-10 15:57:10 -08001935 unregisterHomeVisibilityObserver();
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001936 }
1937
Malcolm Chen549e21a2020-01-10 15:57:10 -08001938 private synchronized void unregisterHomeVisibilityObserver() {
Hall Liu9d5d5ee2020-10-06 14:15:40 -07001939 if (mHomeVisibilityListener != null) {
Malcolm Chen549e21a2020-01-10 15:57:10 -08001940 ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
Hall Liu9d5d5ee2020-10-06 14:15:40 -07001941 am.removeHomeVisibilityListener(mHomeVisibilityListener);
Malcolm Chen549e21a2020-01-10 15:57:10 -08001942 CatLog.d(LOG_TAG, "Stopped to observe the foreground activity");
Hall Liu9d5d5ee2020-10-06 14:15:40 -07001943 mHomeVisibilityListener = null;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09001944 }
1945 }
1946
Yoshiaki Naka0c2d2ba2017-11-17 21:51:55 +09001947 private synchronized void registerLocaleChangeReceiver() {
1948 if (mLocaleChangeReceiver == null) {
1949 mLocaleChangeReceiver = new BroadcastReceiver() {
1950 @Override public void onReceive(Context context, Intent intent) {
1951 if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
Yoshiaki Nakab80f8ce2019-04-25 14:36:03 +09001952 Message message = mServiceHandler.obtainMessage(OP_LOCALE_CHANGED);
Yoshiaki Naka0c2d2ba2017-11-17 21:51:55 +09001953 mServiceHandler.sendMessage(message);
1954 }
1955 }
1956 };
1957 registerReceiver(mLocaleChangeReceiver, new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
1958 }
1959 }
1960
1961 private synchronized void unregisterLocaleChangeReceiver() {
1962 if (mLocaleChangeReceiver != null) {
1963 unregisterReceiver(mLocaleChangeReceiver);
1964 mLocaleChangeReceiver = null;
1965 }
1966 }
1967
Preeti Ahuja95919342013-10-01 18:18:55 -07001968 private void sendSetUpEventResponse(int event, byte[] addedInfo, int slotId) {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09001969 CatLog.d(LOG_TAG, "sendSetUpEventResponse: event : " + event + "slotId = " + slotId);
Preeti Ahuja95919342013-10-01 18:18:55 -07001970
1971 if (mStkContext[slotId].mCurrentSetupEventCmd == null){
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09001972 CatLog.e(LOG_TAG, "mCurrentSetupEventCmd is null");
Preeti Ahuja95919342013-10-01 18:18:55 -07001973 return;
1974 }
1975
1976 CatResponseMessage resMsg = new CatResponseMessage(mStkContext[slotId].mCurrentSetupEventCmd);
1977
1978 resMsg.setResultCode(ResultCode.OK);
1979 resMsg.setEventDownload(event, addedInfo);
1980
1981 mStkService[slotId].onCmdResponse(resMsg);
1982 }
1983
1984 private void checkForSetupEvent(int event, Bundle args, int slotId) {
1985 boolean eventPresent = false;
1986 byte[] addedInfo = null;
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09001987 CatLog.d(LOG_TAG, "Event :" + event);
Preeti Ahuja95919342013-10-01 18:18:55 -07001988
1989 if (mStkContext[slotId].mSetupEventListSettings != null) {
1990 /* Checks if the event is present in the EventList updated by last
1991 * SetupEventList Proactive Command */
1992 for (int i : mStkContext[slotId].mSetupEventListSettings.eventList) {
1993 if (event == i) {
1994 eventPresent = true;
1995 break;
1996 }
1997 }
1998
1999 /* If Event is present send the response to ICC */
2000 if (eventPresent == true) {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09002001 CatLog.d(LOG_TAG, " Event " + event + "exists in the EventList");
Preeti Ahuja95919342013-10-01 18:18:55 -07002002
2003 switch (event) {
Yoshiaki Nakafb997252017-09-19 20:14:58 +09002004 case USER_ACTIVITY_EVENT:
Preeti Ahuja560be362014-11-25 19:38:24 -08002005 case IDLE_SCREEN_AVAILABLE_EVENT:
2006 sendSetUpEventResponse(event, addedInfo, slotId);
2007 removeSetUpEvent(event, slotId);
2008 break;
Preeti Ahuja95919342013-10-01 18:18:55 -07002009 case LANGUAGE_SELECTION_EVENT:
2010 String language = mContext
2011 .getResources().getConfiguration().locale.getLanguage();
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09002012 CatLog.d(LOG_TAG, "language: " + language);
Preeti Ahuja95919342013-10-01 18:18:55 -07002013 // Each language code is a pair of alpha-numeric characters.
2014 // Each alpha-numeric character shall be coded on one byte
2015 // using the SMS default 7-bit coded alphabet
2016 addedInfo = GsmAlphabet.stringToGsm8BitPacked(language);
2017 sendSetUpEventResponse(event, addedInfo, slotId);
2018 break;
feizhang5fd5c6f2021-06-30 13:59:02 +08002019 //add by qingyang.yi 2016.6.21 PR:1137553 add for Browser termination EVENT
2020 case BROWSER_TERMINATION_EVENT:
2021 int browserTerminationCause = args.getInt(BROWSER_TERMINATION_CAUSE);
2022 CatLog.d(this, "BrowserTerminationCause: " + browserTerminationCause);
2023 // Single byte is sufficient to represent browser termination cause.
2024 addedInfo = new byte[1];
2025 addedInfo[0] = (byte) browserTerminationCause;
2026 sendSetUpEventResponse(event, addedInfo, slotId);
2027 break;
2028 //add end by qingyang.yi
Preeti Ahuja95919342013-10-01 18:18:55 -07002029 default:
2030 break;
2031 }
2032 } else {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09002033 CatLog.e(LOG_TAG, " Event does not exist in the EventList");
Preeti Ahuja95919342013-10-01 18:18:55 -07002034 }
2035 } else {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09002036 CatLog.e(LOG_TAG, "SetupEventList is not received. Ignoring the event: " + event);
Preeti Ahuja95919342013-10-01 18:18:55 -07002037 }
2038 }
2039
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09002040 private void removeSetUpEvent(int event, int slotId) {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09002041 CatLog.d(LOG_TAG, "Remove Event :" + event);
Preeti Ahuja95919342013-10-01 18:18:55 -07002042
2043 if (mStkContext[slotId].mSetupEventListSettings != null) {
2044 /*
2045 * Make new Eventlist without the event
2046 */
2047 for (int i = 0; i < mStkContext[slotId].mSetupEventListSettings.eventList.length; i++) {
2048 if (event == mStkContext[slotId].mSetupEventListSettings.eventList[i]) {
2049 mStkContext[slotId].mSetupEventListSettings.eventList[i] = INVALID_SETUP_EVENT;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09002050
2051 switch (event) {
Yoshiaki Nakafb997252017-09-19 20:14:58 +09002052 case USER_ACTIVITY_EVENT:
2053 // The broadcast receiver can be unregistered
2054 // as the event has already been sent to the card.
2055 unregisterUserActivityReceiver();
2056 break;
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09002057 case IDLE_SCREEN_AVAILABLE_EVENT:
2058 // The process observer can be unregistered
2059 // as the idle screen has already been available.
Malcolm Chen549e21a2020-01-10 15:57:10 -08002060 unregisterHomeVisibilityObserver();
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09002061 break;
2062 default:
2063 break;
2064 }
Preeti Ahuja95919342013-10-01 18:18:55 -07002065 break;
2066 }
2067 }
2068 }
2069 }
2070
2071 private void launchEventMessage(int slotId) {
2072 launchEventMessage(slotId, mStkContext[slotId].mCurrentCmd.geTextMessage());
2073 }
2074
Wink Savillee68857d2014-10-17 15:23:05 -07002075 private void launchEventMessage(int slotId, TextMessage msg) {
Ryuto Sawada2ba20cc2015-12-28 17:10:35 +01002076 if (msg == null || msg.text == null || (msg.text != null && msg.text.length() == 0)) {
Wink Savillee68857d2014-10-17 15:23:05 -07002077 CatLog.d(LOG_TAG, "launchEventMessage return");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002078 return;
2079 }
Wink Savillee68857d2014-10-17 15:23:05 -07002080
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002081 Toast toast = new Toast(mContext.getApplicationContext());
2082 LayoutInflater inflate = (LayoutInflater) mContext
2083 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
2084 View v = inflate.inflate(R.layout.stk_event_msg, null);
2085 TextView tv = (TextView) v
2086 .findViewById(com.android.internal.R.id.message);
2087 ImageView iv = (ImageView) v
2088 .findViewById(com.android.internal.R.id.icon);
2089 if (msg.icon != null) {
Umashankar Godachic77445b2018-02-28 02:51:56 +05302090 iv.setContentDescription(TEXT_ICON_FROM_COMMAND);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002091 iv.setImageBitmap(msg.icon);
2092 } else {
2093 iv.setVisibility(View.GONE);
2094 }
Preeti Ahujaf33bf392013-09-28 19:11:31 +05302095 /* In case of 'self explanatory' stkapp should display the specified
2096 * icon in proactive command (but not the alpha string).
2097 * If icon is non-self explanatory and if the icon could not be displayed
2098 * then alpha string or text data should be displayed
2099 * Ref: ETSI 102.223,section 6.5.4
2100 */
2101 if (mStkContext[slotId].mCurrentCmd.hasIconLoadFailed() ||
2102 msg.icon == null || !msg.iconSelfExplanatory) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002103 tv.setText(msg.text);
2104 }
2105
2106 toast.setView(v);
2107 toast.setDuration(Toast.LENGTH_LONG);
2108 toast.setGravity(Gravity.BOTTOM, 0, 0);
2109 toast.show();
2110 }
2111
Wink Savillee68857d2014-10-17 15:23:05 -07002112 private void launchConfirmationDialog(TextMessage msg, int slotId) {
2113 msg.title = mStkContext[slotId].lastSelectedItem;
2114 Intent newIntent = new Intent();
2115 String targetActivity = STK_DIALOG_ACTIVITY_NAME;
2116 String uriString = STK_DIALOG_URI + System.currentTimeMillis();
2117 //Set unique URI to create a new instance of activity for different slotId.
2118 Uri uriData = Uri.parse(uriString);
2119
Yuta Uife965802017-11-07 20:12:37 +09002120 newIntent.setClassName(this, targetActivity);
2121 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
2122 | Intent.FLAG_ACTIVITY_NO_HISTORY
2123 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
2124 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
2125 newIntent.putExtra("TEXT", msg);
2126 newIntent.putExtra(SLOT_ID, slotId);
2127 newIntent.setData(uriData);
2128 startActivity(newIntent);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002129 }
2130
2131 private void launchBrowser(BrowserSettings settings) {
2132 if (settings == null) {
2133 return;
2134 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002135
Abhishek Adappa840c82f2013-02-26 10:19:49 -08002136 Uri data = null;
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07002137 String url;
2138 if (settings.url == null) {
Abhishek Adappa840c82f2013-02-26 10:19:49 -08002139 // if the command did not contain a URL,
2140 // launch the browser to the default homepage.
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09002141 CatLog.d(LOG_TAG, "no url data provided by proactive command." +
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07002142 " launching browser with stk default URL ... ");
2143 url = SystemProperties.get(STK_BROWSER_DEFAULT_URL_SYSPROP,
2144 "http://www.google.com");
2145 } else {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09002146 CatLog.d(LOG_TAG, "launch browser command has attached url = " + settings.url);
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07002147 url = settings.url;
Abhishek Adappa840c82f2013-02-26 10:19:49 -08002148 }
David Brown7c03cfe2011-10-20 15:36:12 -07002149
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07002150 if (url.startsWith("http://") || url.startsWith("https://")) {
2151 data = Uri.parse(url);
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09002152 CatLog.d(LOG_TAG, "launching browser with url = " + url);
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07002153 } else {
2154 String modifiedUrl = "http://" + url;
2155 data = Uri.parse(modifiedUrl);
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09002156 CatLog.d(LOG_TAG, "launching browser with modified url = " + modifiedUrl);
Preeti Ahujaa7cdca22013-10-01 18:20:56 -07002157 }
2158
2159 Intent intent = new Intent(Intent.ACTION_VIEW);
2160 intent.setData(data);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002161 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2162 switch (settings.mode) {
2163 case USE_EXISTING_BROWSER:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002164 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
2165 break;
2166 case LAUNCH_NEW_BROWSER:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002167 intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
2168 break;
2169 case LAUNCH_IF_NOT_ALREADY_LAUNCHED:
2170 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
2171 break;
2172 }
2173 // start browser activity
2174 startActivity(intent);
2175 // a small delay, let the browser start, before processing the next command.
Wink Saville79085fc2009-06-09 10:27:23 -07002176 // this is good for scenarios where a related DISPLAY TEXT command is
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002177 // followed immediately.
2178 try {
Ryuto Sawada350aaa62016-06-13 14:47:22 +09002179 Thread.sleep(3000);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002180 } catch (InterruptedException e) {}
2181 }
2182
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09002183 private void cancelIdleText(int slotId) {
Malcolm Chen549e21a2020-01-10 15:57:10 -08002184 unregisterHomeVisibilityObserver(AppInterface.CommandType.SET_UP_IDLE_MODE_TEXT, slotId);
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09002185 mNotificationManager.cancel(getNotificationId(slotId));
2186 mStkContext[slotId].mIdleModeTextCmd = null;
2187 mStkContext[slotId].mIdleModeTextVisible = false;
2188 }
2189
Wink Savillee68857d2014-10-17 15:23:05 -07002190 private void launchIdleText(int slotId) {
Preeti Ahuja560be362014-11-25 19:38:24 -08002191 TextMessage msg = mStkContext[slotId].mIdleModeTextCmd.geTextMessage();
dujin.cha2a0eb2a2011-11-11 15:03:57 +09002192
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09002193 if (msg != null && !TextUtils.isEmpty(msg.text)) {
Preeti Ahuja95919342013-10-01 18:18:55 -07002194 CatLog.d(LOG_TAG, "launchIdleText - text[" + msg.text
2195 + "] iconSelfExplanatory[" + msg.iconSelfExplanatory
2196 + "] icon[" + msg.icon + "], sim id: " + slotId);
Wink Savillee68857d2014-10-17 15:23:05 -07002197 CatLog.d(LOG_TAG, "Add IdleMode text");
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01002198 PendingIntent pendingIntent = PendingIntent.getService(mContext, 0,
Jordan Liu79bc9422021-02-19 15:29:14 -08002199 new Intent(mContext, StkAppService.class), PendingIntent.FLAG_IMMUTABLE);
fionaxu805eb572017-05-02 10:57:30 -07002200 createAllChannels();
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01002201 final Notification.Builder notificationBuilder = new Notification.Builder(
fionaxu2c91c752017-04-21 18:11:57 -07002202 StkAppService.this, STK_NOTIFICATION_CHANNEL_ID);
Zhang Renjie717bb8d2021-08-20 17:38:24 +08002203 // add by T2M.zhangrenjie for FP4-2257 2021-08-20 begin
2204 /*if (mStkContext[slotId].mMainCmd != null &&
Wink Savillee68857d2014-10-17 15:23:05 -07002205 mStkContext[slotId].mMainCmd.getMenu() != null) {
2206 notificationBuilder.setContentTitle(mStkContext[slotId].mMainCmd.getMenu().title);
Christopher Posselwhite2ad2ab72013-05-27 07:51:06 +02002207 } else {
2208 notificationBuilder.setContentTitle("");
Zhang Renjie717bb8d2021-08-20 17:38:24 +08002209 }*/
Zhang Renjiec8ecd5f2021-08-27 16:45:50 +08002210 Bundle extras = new Bundle();
2211 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, " ");
2212 notificationBuilder.addExtras(extras);
Zhang Renjie717bb8d2021-08-20 17:38:24 +08002213 notificationBuilder.setContentTitle("");
2214 // add by T2M.zhangrenjie for FP4-2257 2021-08-20 end
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01002215 notificationBuilder
Sooraj Sasindran2b44d5b2020-01-29 15:17:48 -08002216 .setSmallIcon(R.drawable.stat_notify_sim_toolkit);
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01002217 notificationBuilder.setContentIntent(pendingIntent);
2218 notificationBuilder.setOngoing(true);
Umashankar Godachid3598a22018-03-01 02:20:28 +05302219 notificationBuilder.setStyle(new Notification.BigTextStyle(notificationBuilder)
2220 .bigText(msg.text));
Yuta Uife965802017-11-07 20:12:37 +09002221 notificationBuilder.setOnlyAlertOnce(true);
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01002222 // Set text and icon for the status bar and notification body.
Preeti Ahujaf33bf392013-09-28 19:11:31 +05302223 if (mStkContext[slotId].mIdleModeTextCmd.hasIconLoadFailed() ||
2224 !msg.iconSelfExplanatory) {
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01002225 notificationBuilder.setContentText(msg.text);
Christopher Posselwhite2ad2ab72013-05-27 07:51:06 +02002226 notificationBuilder.setTicker(msg.text);
samalinc7f3bdf2018-04-26 15:04:31 +08002227 notificationBuilder.setStyle(new Notification.BigTextStyle(notificationBuilder)
2228 .bigText(msg.text));
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01002229 }
2230 if (msg.icon != null) {
2231 notificationBuilder.setLargeIcon(msg.icon);
2232 } else {
2233 Bitmap bitmapIcon = BitmapFactory.decodeResource(StkAppService.this
2234 .getResources().getSystem(),
Sooraj Sasindran2b44d5b2020-01-29 15:17:48 -08002235 R.drawable.stat_notify_sim_toolkit);
Alex Khlivnuik50e0a1d2013-01-25 12:50:48 +01002236 notificationBuilder.setLargeIcon(bitmapIcon);
2237 }
Selim Cinek62eb3fe2014-08-27 17:52:23 +02002238 notificationBuilder.setColor(mContext.getResources().getColor(
2239 com.android.internal.R.color.system_notification_accent_color));
Wink Savillee68857d2014-10-17 15:23:05 -07002240 mNotificationManager.notify(getNotificationId(slotId), notificationBuilder.build());
Yoshiaki Naka62bfb0d2017-10-07 16:42:08 +09002241 mStkContext[slotId].mIdleModeTextVisible = true;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002242 }
2243 }
2244
fionaxu805eb572017-05-02 10:57:30 -07002245 /** Creates the notification channel and registers it with NotificationManager.
2246 * If a channel with the same ID is already registered, NotificationManager will
2247 * ignore this call.
2248 */
2249 private void createAllChannels() {
Yuta Uife965802017-11-07 20:12:37 +09002250 NotificationChannel notificationChannel = new NotificationChannel(
fionaxu805eb572017-05-02 10:57:30 -07002251 STK_NOTIFICATION_CHANNEL_ID,
2252 getResources().getString(R.string.stk_channel_name),
Yuta Uife965802017-11-07 20:12:37 +09002253 NotificationManager.IMPORTANCE_DEFAULT);
2254
2255 notificationChannel.enableVibration(true);
2256 notificationChannel.setVibrationPattern(VIBRATION_PATTERN);
2257
2258 mNotificationManager.createNotificationChannel(notificationChannel);
fionaxu805eb572017-05-02 10:57:30 -07002259 }
2260
Wink Savillee68857d2014-10-17 15:23:05 -07002261 private void launchToneDialog(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002262 Intent newIntent = new Intent(this, ToneDialog.class);
Wink Savillee68857d2014-10-17 15:23:05 -07002263 String uriString = STK_TONE_URI + slotId;
2264 Uri uriData = Uri.parse(uriString);
2265 //Set unique URI to create a new instance of activity for different slotId.
2266 CatLog.d(LOG_TAG, "launchToneDialog, slotId: " + slotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002267 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
2268 | Intent.FLAG_ACTIVITY_NO_HISTORY
2269 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
Wink Savillee68857d2014-10-17 15:23:05 -07002270 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
2271 newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
2272 newIntent.putExtra("TONE", mStkContext[slotId].mCurrentCmd.getToneSettings());
2273 newIntent.putExtra(SLOT_ID, slotId);
2274 newIntent.setData(uriData);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002275 startActivity(newIntent);
2276 }
2277
Srikanth Chintala89aa6602014-03-14 16:26:57 +05302278 private void handlePlayTone(int slotId) {
2279 TextMessage toneMsg = mStkContext[slotId].mCurrentCmd.geTextMessage();
2280
2281 boolean showUser = true;
2282 boolean displayDialog = true;
2283 Resources resource = Resources.getSystem();
2284 try {
2285 displayDialog = !resource.getBoolean(
Sooraj Sasindran2b44d5b2020-01-29 15:17:48 -08002286 R.bool.config_stkNoAlphaUsrCnf);
Srikanth Chintala89aa6602014-03-14 16:26:57 +05302287 } catch (NotFoundException e) {
2288 displayDialog = true;
2289 }
2290
2291 // As per the spec 3GPP TS 11.14, 6.4.5. Play Tone.
2292 // If there is no alpha identifier tlv present, UE may show the
2293 // user information. 'config_stkNoAlphaUsrCnf' value will decide
2294 // whether to show it or not.
2295 // If alpha identifier tlv is present and its data is null, play only tone
2296 // without showing user any information.
2297 // Alpha Id is Present, but the text data is null.
2298 if ((toneMsg.text != null ) && (toneMsg.text.equals(""))) {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09002299 CatLog.d(LOG_TAG, "Alpha identifier data is null, play only tone");
Srikanth Chintala89aa6602014-03-14 16:26:57 +05302300 showUser = false;
2301 }
2302 // Alpha Id is not present AND we need to show info to the user.
2303 if (toneMsg.text == null && displayDialog) {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09002304 CatLog.d(LOG_TAG, "toneMsg.text " + toneMsg.text
Srikanth Chintala89aa6602014-03-14 16:26:57 +05302305 + " Starting ToneDialog activity with default message.");
2306 toneMsg.text = getResources().getString(R.string.default_tone_dialog_msg);
2307 showUser = true;
2308 }
2309 // Dont show user info, if config setting is true.
2310 if (toneMsg.text == null && !displayDialog) {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09002311 CatLog.d(LOG_TAG, "config value stkNoAlphaUsrCnf is true");
Srikanth Chintala89aa6602014-03-14 16:26:57 +05302312 showUser = false;
2313 }
2314
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09002315 CatLog.d(LOG_TAG, "toneMsg.text: " + toneMsg.text + "showUser: " +showUser +
Srikanth Chintala89aa6602014-03-14 16:26:57 +05302316 "displayDialog: " +displayDialog);
2317 playTone(showUser, slotId);
2318 }
2319
2320 private void playTone(boolean showUserInfo, int slotId) {
2321 // Start playing tone and vibration
2322 ToneSettings settings = mStkContext[slotId].mCurrentCmd.getToneSettings();
2323 if (null == settings) {
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09002324 CatLog.d(LOG_TAG, "null settings, not playing tone.");
Srikanth Chintala89aa6602014-03-14 16:26:57 +05302325 return;
2326 }
2327
2328 mVibrator = (Vibrator)getSystemService(VIBRATOR_SERVICE);
2329 mTonePlayer = new TonePlayer();
2330 mTonePlayer.play(settings.tone);
2331 int timeout = StkApp.calculateDurationInMilis(settings.duration);
2332 if (timeout == 0) {
2333 timeout = StkApp.TONE_DEFAULT_TIMEOUT;
2334 }
2335
Yoshiaki Nakab80f8ce2019-04-25 14:36:03 +09002336 Message msg = mServiceHandler.obtainMessage(OP_STOP_TONE, 0, slotId,
2337 (showUserInfo ? PLAY_TONE_WITH_DIALOG : PLAY_TONE_ONLY));
Srikanth Chintala89aa6602014-03-14 16:26:57 +05302338 mServiceHandler.sendMessageDelayed(msg, timeout);
2339 if (settings.vibrate) {
2340 mVibrator.vibrate(timeout);
2341 }
2342
2343 // Start Tone dialog Activity to show user the information.
2344 if (showUserInfo) {
2345 Intent newIntent = new Intent(sInstance, ToneDialog.class);
2346 String uriString = STK_TONE_URI + slotId;
2347 Uri uriData = Uri.parse(uriString);
2348 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
Srikanth Chintala89aa6602014-03-14 16:26:57 +05302349 | Intent.FLAG_ACTIVITY_SINGLE_TOP
Srikanth Chintala89aa6602014-03-14 16:26:57 +05302350 | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
2351 newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
Umashankar Godachid345b362017-11-27 15:46:55 +05302352 newIntent.putExtra("TONE", mStkContext[slotId].mCurrentCmd.getToneSettings());
Srikanth Chintala89aa6602014-03-14 16:26:57 +05302353 newIntent.putExtra(SLOT_ID, slotId);
2354 newIntent.setData(uriData);
2355 startActivity(newIntent);
2356 }
2357 }
2358
Srikanth Chintala89aa6602014-03-14 16:26:57 +05302359 private void handleStopTone(Message msg, int slotId) {
2360 int resId = 0;
2361
2362 // Stop the play tone in following cases:
2363 // 1.OP_STOP_TONE: play tone timer expires.
2364 // 2.STOP_TONE_USER: user pressed the back key.
Yoshiaki Nakab80f8ce2019-04-25 14:36:03 +09002365 if (msg.what == OP_STOP_TONE) {
Srikanth Chintala89aa6602014-03-14 16:26:57 +05302366 resId = RES_ID_DONE;
Yoshiaki Nakab80f8ce2019-04-25 14:36:03 +09002367 } else if (msg.what == OP_STOP_TONE_USER) {
Srikanth Chintala89aa6602014-03-14 16:26:57 +05302368 resId = RES_ID_END_SESSION;
2369 }
2370
2371 sendResponse(resId, slotId, true);
Yoshiaki Nakab80f8ce2019-04-25 14:36:03 +09002372
2373 mServiceHandler.removeMessages(OP_STOP_TONE);
2374 mServiceHandler.removeMessages(OP_STOP_TONE_USER);
2375
Takanori Nakanob82c8752019-04-01 14:47:07 +09002376 if (mTonePlayer != null) {
Srikanth Chintala89aa6602014-03-14 16:26:57 +05302377 mTonePlayer.stop();
2378 mTonePlayer.release();
2379 mTonePlayer = null;
2380 }
2381 if (mVibrator != null) {
2382 mVibrator.cancel();
2383 mVibrator = null;
2384 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002385 }
2386
Yoshiaki Nakafac708c2020-01-22 19:49:27 +09002387 boolean isNoTonePlaying() {
2388 return mTonePlayer == null ? true : false;
2389 }
2390
Takanori Nakano49b12722016-02-16 14:34:14 +09002391 private void launchOpenChannelDialog(final int slotId) {
Wink Savillee68857d2014-10-17 15:23:05 -07002392 TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05002393 if (msg == null) {
Wink Savillee68857d2014-10-17 15:23:05 -07002394 CatLog.d(LOG_TAG, "msg is null, return here");
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05002395 return;
2396 }
2397
2398 msg.title = getResources().getString(R.string.stk_dialog_title);
2399 if (msg.text == null) {
2400 msg.text = getResources().getString(R.string.default_open_channel_msg);
2401 }
2402
2403 final AlertDialog dialog = new AlertDialog.Builder(mContext)
2404 .setIconAttribute(android.R.attr.alertDialogIcon)
2405 .setTitle(msg.title)
2406 .setMessage(msg.text)
2407 .setCancelable(false)
2408 .setPositiveButton(getResources().getString(R.string.stk_dialog_accept),
2409 new DialogInterface.OnClickListener() {
2410 public void onClick(DialogInterface dialog, int which) {
2411 Bundle args = new Bundle();
2412 args.putInt(RES_ID, RES_ID_CHOICE);
2413 args.putInt(CHOICE, YES);
Yoshiaki Nakab80f8ce2019-04-25 14:36:03 +09002414 sendResponse(args, slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05002415 }
2416 })
2417 .setNegativeButton(getResources().getString(R.string.stk_dialog_reject),
2418 new DialogInterface.OnClickListener() {
2419 public void onClick(DialogInterface dialog, int which) {
2420 Bundle args = new Bundle();
2421 args.putInt(RES_ID, RES_ID_CHOICE);
2422 args.putInt(CHOICE, NO);
Yoshiaki Nakab80f8ce2019-04-25 14:36:03 +09002423 sendResponse(args, slotId);
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05002424 }
2425 })
2426 .create();
2427
2428 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
2429 if (!mContext.getResources().getBoolean(
Sooraj Sasindran2b44d5b2020-01-29 15:17:48 -08002430 R.bool.config_sf_slowBlur)) {
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05002431 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
2432 }
2433
2434 dialog.show();
2435 }
2436
Wink Savillee68857d2014-10-17 15:23:05 -07002437 private void launchTransientEventMessage(int slotId) {
2438 TextMessage msg = mStkContext[slotId].mCurrentCmd.geTextMessage();
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05002439 if (msg == null) {
Wink Savillee68857d2014-10-17 15:23:05 -07002440 CatLog.d(LOG_TAG, "msg is null, return here");
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05002441 return;
2442 }
2443
2444 msg.title = getResources().getString(R.string.stk_dialog_title);
2445
2446 final AlertDialog dialog = new AlertDialog.Builder(mContext)
2447 .setIconAttribute(android.R.attr.alertDialogIcon)
2448 .setTitle(msg.title)
2449 .setMessage(msg.text)
2450 .setCancelable(false)
2451 .setPositiveButton(getResources().getString(android.R.string.ok),
2452 new DialogInterface.OnClickListener() {
2453 public void onClick(DialogInterface dialog, int which) {
2454 }
2455 })
2456 .create();
2457
2458 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
Sooraj Sasindran2b44d5b2020-01-29 15:17:48 -08002459 if (!mContext.getResources().getBoolean(R.bool.config_sf_slowBlur)) {
Kazuhiro Ondo764167c2011-10-21 16:05:05 -05002460 dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
2461 }
2462
2463 dialog.show();
2464 }
2465
Wink Savillee68857d2014-10-17 15:23:05 -07002466 private int getNotificationId(int slotId) {
2467 int notifyId = STK_NOTIFICATION_ID;
2468 if (slotId >= 0 && slotId < mSimCount) {
2469 notifyId += slotId;
2470 } else {
2471 CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
2472 }
2473 CatLog.d(LOG_TAG, "getNotificationId, slotId: " + slotId + ", notifyId: " + notifyId);
2474 return notifyId;
2475 }
2476
2477 private String getItemName(int itemId, int slotId) {
2478 Menu menu = mStkContext[slotId].mCurrentCmd.getMenu();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002479 if (menu == null) {
2480 return null;
2481 }
2482 for (Item item : menu.items) {
2483 if (item.id == itemId) {
2484 return item.text;
2485 }
2486 }
2487 return null;
2488 }
2489
Wink Savillee68857d2014-10-17 15:23:05 -07002490 private boolean removeMenu(int slotId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002491 try {
Wink Savillee68857d2014-10-17 15:23:05 -07002492 if (mStkContext[slotId].mCurrentMenu.items.size() == 1 &&
2493 mStkContext[slotId].mCurrentMenu.items.get(0) == null) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002494 return true;
2495 }
2496 } catch (NullPointerException e) {
Wink Savillee68857d2014-10-17 15:23:05 -07002497 CatLog.d(LOG_TAG, "Unable to get Menu's items size");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002498 return true;
2499 }
2500 return false;
2501 }
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +05302502
Yoshiaki Naka58e07652019-04-26 17:58:52 +09002503 private boolean uninstallIfUnnecessary() {
2504 for (int slot = 0; slot < mSimCount; slot++) {
2505 if (mStkContext[slot].mMainCmd != null) {
2506 return false;
2507 }
2508 }
2509 CatLog.d(LOG_TAG, "Uninstall App");
2510 StkAppInstaller.uninstall(this);
2511 return true;
2512 }
2513
Malcolm Chenf961b652019-10-24 19:53:48 -07002514 synchronized StkContext getStkContext(int slotId) {
Wink Savillee68857d2014-10-17 15:23:05 -07002515 if (slotId >= 0 && slotId < mSimCount) {
2516 return mStkContext[slotId];
2517 } else {
2518 CatLog.d(LOG_TAG, "invalid slotId: " + slotId);
2519 return null;
2520 }
2521 }
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +05302522
2523 private void handleAlphaNotify(Bundle args) {
2524 String alphaString = args.getString(AppInterface.ALPHA_STRING);
2525
Yoshiaki Naka3a980db2019-10-30 17:11:33 +09002526 CatLog.d(LOG_TAG, "Alpha string received from card: " + alphaString);
Preeti Ahuja0f4cf2f2012-08-09 11:45:08 +05302527 Toast toast = Toast.makeText(sInstance, alphaString, Toast.LENGTH_LONG);
2528 toast.setGravity(Gravity.TOP, 0, 0);
2529 toast.show();
2530 }
Srikanth Chintalaba103002015-11-30 10:49:52 -08002531
2532 private boolean isUrlAvailableToLaunchBrowser(BrowserSettings settings) {
2533 String url = SystemProperties.get(STK_BROWSER_DEFAULT_URL_SYSPROP, "");
2534 if (url == "" && settings.url == null) {
2535 return false;
2536 }
2537 return true;
2538 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08002539}