blob: 74e89f2add2c27a778c8c26521b80c1f1dbbc9c6 [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
Christopher Posselwhitecfe4d7f2013-09-04 09:01:50 +020019import com.android.internal.telephony.cat.CatLog;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070020import com.android.internal.telephony.cat.TextMessage;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080021
22import android.app.Activity;
w302348bf95af2015-01-09 10:54:41 -080023import android.app.AlarmManager;
Sanket Padawe7b70fb42017-04-05 15:35:34 -070024import android.app.AlertDialog;
w302348bf95af2015-01-09 10:54:41 -080025import android.app.PendingIntent;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080026import android.content.Intent;
w302348bf95af2015-01-09 10:54:41 -080027import android.content.IntentFilter;
28import android.content.BroadcastReceiver;
29import android.content.Context;
Sanket Padawe7b70fb42017-04-05 15:35:34 -070030import android.content.DialogInterface;
Sanket Padawe7b70fb42017-04-05 15:35:34 -070031
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080032import android.os.Bundle;
w302348bf95af2015-01-09 10:54:41 -080033import android.os.SystemClock;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080034
35/**
w302348bf95af2015-01-09 10:54:41 -080036 * AlertDialog used for DISPLAY TEXT commands.
Wink Saville79085fc2009-06-09 10:27:23 -070037 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080038 */
Sanket Padawe7b70fb42017-04-05 15:35:34 -070039public class StkDialogActivity extends Activity {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080040 // members
Wink Savillee68857d2014-10-17 15:23:05 -070041 private static final String className = new Object(){}.getClass().getEnclosingClass().getName();
42 private static final String LOG_TAG = className.substring(className.lastIndexOf('.') + 1);
43 TextMessage mTextMsg = null;
44 private int mSlotId = -1;
45 private StkAppService appService = StkAppService.getInstance();
w302348bf95af2015-01-09 10:54:41 -080046 // Determines whether Terminal Response (TR) has been sent
Johannes Carlssonef243a22011-10-25 10:37:24 +020047 private boolean mIsResponseSent = false;
w302348bf95af2015-01-09 10:54:41 -080048 private Context mContext;
49 // Utilize AlarmManager for real-time countdown
50 private PendingIntent mTimeoutIntent;
51 private AlarmManager mAlarmManager;
52 private final static String ALARM_TIMEOUT = "com.android.stk.DIALOG_ALARM_TIMEOUT";
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080053
Takanori Nakano1d3f3c12016-08-30 10:34:24 +090054 // Keys for saving the state of the dialog in the bundle
55 private static final String TEXT_KEY = "text";
56 private static final String TIMEOUT_INTENT_KEY = "timeout";
57 private static final String SLOT_ID_KEY = "slotid";
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080058
Takanori Nakanocbe32d32017-07-20 17:10:46 +090059 private AlertDialog mAlertDialog;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080060
61 @Override
Takanori Nakano1d3f3c12016-08-30 10:34:24 +090062 protected void onCreate(Bundle savedInstanceState) {
63 super.onCreate(savedInstanceState);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080064
w302348bf95af2015-01-09 10:54:41 -080065 CatLog.d(LOG_TAG, "onCreate, sim id: " + mSlotId);
Ryuto Sawadaba9b86b2016-10-03 14:03:16 +090066
67 // appService can be null if this activity is automatically recreated by the system
68 // with the saved instance state right after the phone process is killed.
69 if (appService == null) {
70 CatLog.d(LOG_TAG, "onCreate - appService is null");
71 finish();
72 return;
73 }
74
w302348bf95af2015-01-09 10:54:41 -080075 // New Dialog is created - set to no response sent
76 mIsResponseSent = false;
77
Takanori Nakanocbe32d32017-07-20 17:10:46 +090078 AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080079
Sanket Padawe7b70fb42017-04-05 15:35:34 -070080 alertDialogBuilder.setPositiveButton(R.string.button_ok, new
81 DialogInterface.OnClickListener() {
82 @Override
83 public void onClick(DialogInterface dialog, int id) {
84 CatLog.d(LOG_TAG, "OK Clicked!, mSlotId: " + mSlotId);
85 cancelTimeOut();
86 sendResponse(StkAppService.RES_ID_CONFIRM, true);
87 finish();
88 }
89 });
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080090
Sanket Padawe7b70fb42017-04-05 15:35:34 -070091 alertDialogBuilder.setNegativeButton(R.string.button_cancel, new
92 DialogInterface.OnClickListener() {
93 @Override
94 public void onClick(DialogInterface dialog,int id) {
95 CatLog.d(LOG_TAG, "Cancel Clicked!, mSlotId: " + mSlotId);
96 cancelTimeOut();
97 sendResponse(StkAppService.RES_ID_CONFIRM, false);
98 finish();
99 }
100 });
Takuro Nishief00cb12017-07-04 11:46:28 +0900101
102 alertDialogBuilder.setOnCancelListener(new DialogInterface.OnCancelListener() {
103 @Override
104 public void onCancel(DialogInterface dialog) {
105 CatLog.d(LOG_TAG, "Moving backward!, mSlotId: " + mSlotId);
106 cancelTimeOut();
107 sendResponse(StkAppService.RES_ID_BACKWARD);
108 finish();
109 }
110 });
111
Sanket Padawe7b70fb42017-04-05 15:35:34 -0700112 alertDialogBuilder.create();
w302348bf95af2015-01-09 10:54:41 -0800113
Takanori Nakanocbe32d32017-07-20 17:10:46 +0900114 initFromIntent(getIntent());
115 if (mTextMsg == null) {
116 finish();
117 return;
118 }
119
120 if (!mTextMsg.responseNeeded) {
121 alertDialogBuilder.setNegativeButton(null, null);
122 }
123
124 alertDialogBuilder.setTitle(mTextMsg.title);
125
126 if (!(mTextMsg.iconSelfExplanatory && mTextMsg.icon != null)) {
127 alertDialogBuilder.setMessage(mTextMsg.text);
128 }
129
130 mAlertDialog = alertDialogBuilder.create();
131 mAlertDialog.setCanceledOnTouchOutside(false);
132 mAlertDialog.show();
133
w302348bf95af2015-01-09 10:54:41 -0800134 mContext = getBaseContext();
135 IntentFilter intentFilter = new IntentFilter();
136 intentFilter.addAction(ALARM_TIMEOUT);
137 mContext.registerReceiver(mBroadcastReceiver, intentFilter);
138 mAlarmManager =(AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800139 }
140
141 @Override
142 public void onResume() {
143 super.onResume();
Wink Savillee68857d2014-10-17 15:23:05 -0700144 CatLog.d(LOG_TAG, "onResume - mIsResponseSent[" + mIsResponseSent +
145 "], sim id: " + mSlotId);
Preeti Ahuja414bc412013-06-25 19:31:49 -0700146
Christopher Posselwhitecfe4d7f2013-09-04 09:01:50 +0200147 /*
Preeti Ahuja414bc412013-06-25 19:31:49 -0700148 * If the userClear flag is set and dialogduration is set to 0, the display Text
149 * should be displayed to user forever until some high priority event occurs
150 * (incoming call, MMI code execution etc as mentioned under section
151 * ETSI 102.223, 6.4.1)
Christopher Posselwhitecfe4d7f2013-09-04 09:01:50 +0200152 */
Preeti Ahuja414bc412013-06-25 19:31:49 -0700153 if (StkApp.calculateDurationInMilis(mTextMsg.duration) == 0 &&
Sanket Padawe7b70fb42017-04-05 15:35:34 -0700154 !mTextMsg.responseNeeded && mTextMsg.userClear) {
w302348bf95af2015-01-09 10:54:41 -0800155 CatLog.d(LOG_TAG, "User should clear text..showing message forever");
Christopher Posselwhitecfe4d7f2013-09-04 09:01:50 +0200156 return;
157 }
158
Preeti Ahuja95919342013-10-01 18:18:55 -0700159 appService.setDisplayTextDlgVisibility(true, mSlotId);
w302348bf95af2015-01-09 10:54:41 -0800160
161 /*
162 * When another activity takes the foreground, we do not want the Terminal
163 * Response timer to be restarted when our activity resumes. Hence we will
164 * check if there is an existing timer, and resume it. In this way we will
Sanket Padawe7b70fb42017-04-05 15:35:34 -0700165 * inform the SIM in correct time when there is no response from the User
w302348bf95af2015-01-09 10:54:41 -0800166 * to a dialog.
167 */
168 if (mTimeoutIntent != null) {
169 CatLog.d(LOG_TAG, "Pending Alarm! Let it finish counting down...");
170 }
171 else {
172 CatLog.d(LOG_TAG, "No Pending Alarm! OK to start timer...");
173 startTimeOut(mTextMsg.userClear);
174 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800175 }
176
177 @Override
178 public void onPause() {
179 super.onPause();
Wink Savillee68857d2014-10-17 15:23:05 -0700180 CatLog.d(LOG_TAG, "onPause, sim id: " + mSlotId);
Preeti Ahuja95919342013-10-01 18:18:55 -0700181 appService.setDisplayTextDlgVisibility(false, mSlotId);
Preeti Ahuja03be6672012-08-30 19:21:25 +0530182
183 /*
184 * do not cancel the timer here cancelTimeOut(). If any higher/lower
185 * priority events such as incoming call, new sms, screen off intent,
186 * notification alerts, user actions such as 'User moving to another activtiy'
187 * etc.. occur during Display Text ongoing session,
188 * this activity would receive 'onPause()' event resulting in
189 * cancellation of the timer. As a result no terminal response is
190 * sent to the card.
191 */
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800192 }
193
194 @Override
Johannes Carlssonef243a22011-10-25 10:37:24 +0200195 protected void onStart() {
w302348bf95af2015-01-09 10:54:41 -0800196 CatLog.d(LOG_TAG, "onStart, sim id: " + mSlotId);
Johannes Carlssonef243a22011-10-25 10:37:24 +0200197 super.onStart();
Johannes Carlssonef243a22011-10-25 10:37:24 +0200198 }
199
200 @Override
201 public void onStop() {
202 super.onStop();
Wink Savillee68857d2014-10-17 15:23:05 -0700203 CatLog.d(LOG_TAG, "onStop - before Send CONFIRM false mIsResponseSent[" +
204 mIsResponseSent + "], sim id: " + mSlotId);
Takanori Nakano1d3f3c12016-08-30 10:34:24 +0900205
206 // Avoid calling finish() or setPendingDialogInstance()
207 // if the activity is being restarted now.
208 if (isChangingConfigurations()) {
209 return;
210 }
211
Tsukasa Gotou2aa64562016-02-09 18:52:33 +0900212 if (!mTextMsg.responseNeeded) {
213 return;
214 }
Johannes Carlssonef243a22011-10-25 10:37:24 +0200215 if (!mIsResponseSent) {
Wink Savillee68857d2014-10-17 15:23:05 -0700216 appService.getStkContext(mSlotId).setPendingDialogInstance(this);
217 } else {
218 CatLog.d(LOG_TAG, "finish.");
219 appService.getStkContext(mSlotId).setPendingDialogInstance(null);
220 cancelTimeOut();
221 finish();
Johannes Carlssonef243a22011-10-25 10:37:24 +0200222 }
223 }
224
225 @Override
Wink Savillee68857d2014-10-17 15:23:05 -0700226 public void onDestroy() {
227 super.onDestroy();
228 CatLog.d(LOG_TAG, "onDestroy - mIsResponseSent[" + mIsResponseSent +
229 "], sim id: " + mSlotId);
Takanori Nakanocbe32d32017-07-20 17:10:46 +0900230
231 if (mAlertDialog != null && mAlertDialog.isShowing()) {
232 mAlertDialog.dismiss();
233 mAlertDialog = null;
234 }
235
Ryuto Sawadaba9b86b2016-10-03 14:03:16 +0900236 if (appService == null) {
237 return;
238 }
Wink Savillee68857d2014-10-17 15:23:05 -0700239 // if dialog activity is finished by stkappservice
240 // when receiving OP_LAUNCH_APP from the other SIM, we can not send TR here
241 // , since the dialog cmd is waiting user to process.
Takanori Nakano1d3f3c12016-08-30 10:34:24 +0900242 if (!isChangingConfigurations()) {
243 if (!mIsResponseSent && appService != null && !appService.isDialogPending(mSlotId)) {
244 sendResponse(StkAppService.RES_ID_CONFIRM, false);
245 }
246 cancelTimeOut();
Wink Savillee68857d2014-10-17 15:23:05 -0700247 }
w302348bf95af2015-01-09 10:54:41 -0800248 // Cleanup broadcast receivers to avoid leaks
249 if (mBroadcastReceiver != null) {
250 unregisterReceiver(mBroadcastReceiver);
251 }
Wink Savillee68857d2014-10-17 15:23:05 -0700252 }
253
254 @Override
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800255 public void onSaveInstanceState(Bundle outState) {
Wink Savillee68857d2014-10-17 15:23:05 -0700256 CatLog.d(LOG_TAG, "onSaveInstanceState");
257
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800258 super.onSaveInstanceState(outState);
259
Takanori Nakano1d3f3c12016-08-30 10:34:24 +0900260 outState.putParcelable(TEXT_KEY, mTextMsg);
261 outState.putParcelable(TIMEOUT_INTENT_KEY, mTimeoutIntent);
262 outState.putInt(SLOT_ID_KEY, mSlotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800263 }
264
265 @Override
266 public void onRestoreInstanceState(Bundle savedInstanceState) {
267 super.onRestoreInstanceState(savedInstanceState);
Wink Saville79085fc2009-06-09 10:27:23 -0700268
Takanori Nakano1d3f3c12016-08-30 10:34:24 +0900269 mTextMsg = savedInstanceState.getParcelable(TEXT_KEY);
270 mTimeoutIntent = savedInstanceState.getParcelable(TIMEOUT_INTENT_KEY);
271 mSlotId = savedInstanceState.getInt(SLOT_ID_KEY);
272 appService.getStkContext(mSlotId).setPendingDialogInstance(this);
Wink Savillee68857d2014-10-17 15:23:05 -0700273 CatLog.d(LOG_TAG, "onRestoreInstanceState - [" + mTextMsg + "]");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800274 }
275
Preeti Ahuja414bc412013-06-25 19:31:49 -0700276 @Override
277 protected void onNewIntent(Intent intent) {
w302348bf95af2015-01-09 10:54:41 -0800278 CatLog.d(LOG_TAG, "onNewIntent - updating the same Dialog box");
Preeti Ahuja414bc412013-06-25 19:31:49 -0700279 setIntent(intent);
280 }
281
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800282 private void sendResponse(int resId, boolean confirmed) {
Wink Savillee68857d2014-10-17 15:23:05 -0700283 if (mSlotId == -1) {
284 CatLog.d(LOG_TAG, "sim id is invalid");
285 return;
286 }
287
288 if (StkAppService.getInstance() == null) {
289 CatLog.d(LOG_TAG, "Ignore response: id is " + resId);
290 return;
291 }
292
293 CatLog.d(LOG_TAG, "sendResponse resID[" + resId + "] confirmed[" + confirmed + "]");
294
Preeti Ahuja414bc412013-06-25 19:31:49 -0700295 if (mTextMsg.responseNeeded) {
296 Bundle args = new Bundle();
297 args.putInt(StkAppService.OPCODE, StkAppService.OP_RESPONSE);
298 args.putInt(StkAppService.SLOT_ID, mSlotId);
299 args.putInt(StkAppService.RES_ID, resId);
300 args.putBoolean(StkAppService.CONFIRMATION, confirmed);
301 startService(new Intent(this, StkAppService.class).putExtras(args));
302 mIsResponseSent = true;
303 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800304 }
305
306 private void sendResponse(int resId) {
307 sendResponse(resId, true);
308 }
309
310 private void initFromIntent(Intent intent) {
311
312 if (intent != null) {
313 mTextMsg = intent.getParcelableExtra("TEXT");
Wink Savillee68857d2014-10-17 15:23:05 -0700314 mSlotId = intent.getIntExtra(StkAppService.SLOT_ID, -1);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800315 } else {
316 finish();
317 }
Wink Savillee68857d2014-10-17 15:23:05 -0700318
319 CatLog.d(LOG_TAG, "initFromIntent - [" + mTextMsg + "], sim id: " + mSlotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800320 }
321
322 private void cancelTimeOut() {
Wink Savillee68857d2014-10-17 15:23:05 -0700323 CatLog.d(LOG_TAG, "cancelTimeOut: " + mSlotId);
w302348bf95af2015-01-09 10:54:41 -0800324 if (mTimeoutIntent != null) {
325 mAlarmManager.cancel(mTimeoutIntent);
326 mTimeoutIntent = null;
327 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800328 }
329
Christopher.Posselwhite1772c042012-11-22 12:15:54 +0100330 private void startTimeOut(boolean waitForUserToClear) {
Preeti Ahuja414bc412013-06-25 19:31:49 -0700331
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800332 // Reset timeout.
333 cancelTimeOut();
334 int dialogDuration = StkApp.calculateDurationInMilis(mTextMsg.duration);
Christopher.Posselwhite1772c042012-11-22 12:15:54 +0100335 // If duration is specified, this has priority. If not, set timeout
336 // according to condition given by the card.
Wink Savillee68857d2014-10-17 15:23:05 -0700337 if (mTextMsg.userClear == true && mTextMsg.responseNeeded == false) {
338 return;
339 } else {
w302348bf95af2015-01-09 10:54:41 -0800340 // userClear = false. will disappear after a while.
Wink Savillee68857d2014-10-17 15:23:05 -0700341 if (dialogDuration == 0) {
342 if (waitForUserToClear) {
343 dialogDuration = StkApp.DISP_TEXT_WAIT_FOR_USER_TIMEOUT;
344 } else {
345 dialogDuration = StkApp.DISP_TEXT_CLEAR_AFTER_DELAY_TIMEOUT;
346 }
Christopher.Posselwhite1772c042012-11-22 12:15:54 +0100347 }
Wink Savillee68857d2014-10-17 15:23:05 -0700348 CatLog.d(LOG_TAG, "startTimeOut: " + mSlotId);
w302348bf95af2015-01-09 10:54:41 -0800349 Intent mAlarmIntent = new Intent(ALARM_TIMEOUT);
350 mAlarmIntent.putExtra(StkAppService.SLOT_ID, mSlotId);
351 mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, mAlarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
352
353 // Try to use a more stringent timer not affected by system sleep.
354 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
355 mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
Sanket Padawe7b70fb42017-04-05 15:35:34 -0700356 SystemClock.elapsedRealtime() + dialogDuration, mTimeoutIntent);
w302348bf95af2015-01-09 10:54:41 -0800357 }
358 else {
359 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
Sanket Padawe7b70fb42017-04-05 15:35:34 -0700360 SystemClock.elapsedRealtime() + dialogDuration, mTimeoutIntent);
w302348bf95af2015-01-09 10:54:41 -0800361 }
Wink Savillee68857d2014-10-17 15:23:05 -0700362 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800363 }
w302348bf95af2015-01-09 10:54:41 -0800364
365 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
366 @Override public void onReceive(Context context, Intent intent) {
367 String action = intent.getAction();
368 int slotID = intent.getIntExtra(StkAppService.SLOT_ID, 0);
369
370 if (action == null || slotID != mSlotId) return;
371 CatLog.d(LOG_TAG, "onReceive, action=" + action + ", sim id: " + slotID);
372 if (action.equals(ALARM_TIMEOUT)) {
373 CatLog.d(LOG_TAG, "ALARM_TIMEOUT rcvd");
374 mTimeoutIntent = null;
375 sendResponse(StkAppService.RES_ID_TIMEOUT);
376 finish();
377 }
378 }
379 };
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800380}