blob: 26ae4cec2fe11b3146c4186af9c13577bd7d1c87 [file] [log] [blame]
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
Wink Saville79085fc2009-06-09 10:27:23 -07003 *
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +09004 * 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
Wink Saville79085fc2009-06-09 10:27:23 -07007 *
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +09008 * http://www.apache.org/licenses/LICENSE-2.0
Wink Saville79085fc2009-06-09 10:27:23 -07009 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080010 * 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
Takanori Nakano48544352016-12-02 18:32:59 +090019import android.app.ActionBar;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080020import android.app.Activity;
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +090021import android.app.AlarmManager;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080022import android.content.Context;
23import android.content.Intent;
Yoshiaki Naka28313ba2017-08-04 12:20:53 +090024import android.content.res.Configuration;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080025import android.os.Bundle;
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +090026import android.os.SystemClock;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080027import android.text.Editable;
28import android.text.InputFilter;
Yoshiaki Nakadd0dbb12017-08-03 21:20:38 +090029import android.text.TextUtils;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080030import android.text.TextWatcher;
31import android.text.method.PasswordTransformationMethod;
32import android.view.KeyEvent;
Yoshiaki Naka28313ba2017-08-04 12:20:53 +090033import android.view.Menu;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080034import android.view.MenuItem;
35import android.view.View;
Kazuhiro Uto12870912018-07-18 17:43:56 +090036import android.view.WindowManager;
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +090037import android.view.inputmethod.EditorInfo;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080038import android.widget.Button;
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +090039import android.widget.EditText;
Takanori Nakano48544352016-12-02 18:32:59 +090040import android.widget.ImageView;
Yoshiaki Naka28313ba2017-08-04 12:20:53 +090041import android.widget.PopupMenu;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080042import android.widget.TextView;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080043import android.widget.TextView.BufferType;
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +090044
Wink Savillee68857d2014-10-17 15:23:05 -070045import com.android.internal.telephony.cat.CatLog;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070046import com.android.internal.telephony.cat.Input;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080047
48/**
49 * Display a request for a text input a long with a text edit form.
50 */
51public class StkInputActivity extends Activity implements View.OnClickListener,
52 TextWatcher {
53
54 // Members
55 private int mState;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080056 private EditText mTextIn = null;
57 private TextView mPromptView = null;
Yoshiaki Naka28313ba2017-08-04 12:20:53 +090058 private View mMoreOptions = null;
59 private PopupMenu mPopupMenu = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080060 private View mYesNoLayout = null;
61 private View mNormalLayout = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080062
63 // Constants
Wink Savillee68857d2014-10-17 15:23:05 -070064 private static final String className = new Object(){}.getClass().getEnclosingClass().getName();
65 private static final String LOG_TAG = className.substring(className.lastIndexOf('.') + 1);
66
67 private Input mStkInput = null;
Wink Savillee68857d2014-10-17 15:23:05 -070068 // Constants
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080069 private static final int STATE_TEXT = 1;
70 private static final int STATE_YES_NO = 2;
71
72 static final String YES_STR_RESPONSE = "YES";
73 static final String NO_STR_RESPONSE = "NO";
74
75 // Font size factor values.
76 static final float NORMAL_FONT_FACTOR = 1;
77 static final float LARGE_FONT_FACTOR = 2;
78 static final float SMALL_FONT_FACTOR = (1 / 2);
79
Takanori Nakano1a672e62017-10-19 19:49:38 +090080 // Keys for saving the state of the activity in the bundle
Takanori Nakano1a672e62017-10-19 19:49:38 +090081 private static final String RESPONSE_SENT_KEY = "response_sent";
82 private static final String INPUT_STRING_KEY = "input_string";
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +090083 private static final String ALARM_TIME_KEY = "alarm_time";
Yoshiaki Naka03a79d92018-08-09 18:41:31 +090084 private static final String PENDING = "pending";
Takanori Nakano1a672e62017-10-19 19:49:38 +090085
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +090086 private static final String INPUT_ALARM_TAG = LOG_TAG;
87 private static final long NO_INPUT_ALARM = -1;
88 private long mAlarmTime = NO_INPUT_ALARM;
89
Wink Savillee68857d2014-10-17 15:23:05 -070090 private StkAppService appService = StkAppService.getInstance();
91
92 private boolean mIsResponseSent = false;
Yoshiaki Naka03a79d92018-08-09 18:41:31 +090093 // Determines whether this is in the pending state.
94 private boolean mIsPending = false;
Wink Savillee68857d2014-10-17 15:23:05 -070095 private int mSlotId = -1;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080096
97 // Click listener to handle buttons press..
98 public void onClick(View v) {
99 String input = null;
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +0900100 if (mIsResponseSent) {
101 CatLog.d(LOG_TAG, "Already responded");
Wink Savillee68857d2014-10-17 15:23:05 -0700102 return;
103 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800104
105 switch (v.getId()) {
106 case R.id.button_ok:
107 // Check that text entered is valid .
108 if (!verfiyTypedText()) {
Wink Savillee68857d2014-10-17 15:23:05 -0700109 CatLog.d(LOG_TAG, "handleClick, invalid text");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800110 return;
111 }
112 input = mTextIn.getText().toString();
113 break;
Takanori Nakano260df9a2017-12-05 22:26:30 +0900114 case R.id.button_cancel:
Takanori Nakano260df9a2017-12-05 22:26:30 +0900115 sendResponse(StkAppService.RES_ID_END_SESSION);
Yoshiaki Naka03a79d92018-08-09 18:41:31 +0900116 finish();
Takanori Nakano260df9a2017-12-05 22:26:30 +0900117 return;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800118 // Yes/No layout buttons.
119 case R.id.button_yes:
120 input = YES_STR_RESPONSE;
121 break;
122 case R.id.button_no:
123 input = NO_STR_RESPONSE;
124 break;
Yoshiaki Naka28313ba2017-08-04 12:20:53 +0900125 case R.id.more:
126 if (mPopupMenu == null) {
127 mPopupMenu = new PopupMenu(this, v);
128 Menu menu = mPopupMenu.getMenu();
129 createOptionsMenuInternal(menu);
130 prepareOptionsMenuInternal(menu);
131 mPopupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
132 public boolean onMenuItemClick(MenuItem item) {
133 optionsItemSelectedInternal(item);
134 return true;
135 }
136 });
137 mPopupMenu.setOnDismissListener(new PopupMenu.OnDismissListener() {
138 public void onDismiss(PopupMenu menu) {
139 mPopupMenu = null;
140 }
141 });
142 mPopupMenu.show();
143 }
144 return;
145 default:
146 break;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800147 }
Wink Savillee68857d2014-10-17 15:23:05 -0700148 CatLog.d(LOG_TAG, "handleClick, ready to response");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800149 sendResponse(StkAppService.RES_ID_INPUT, input, false);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800150 }
151
152 @Override
Takanori Nakano1a672e62017-10-19 19:49:38 +0900153 public void onCreate(Bundle savedInstanceState) {
154 super.onCreate(savedInstanceState);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800155
Wink Savillee68857d2014-10-17 15:23:05 -0700156 CatLog.d(LOG_TAG, "onCreate - mIsResponseSent[" + mIsResponseSent + "]");
157
Ryuto Sawadaba9b86b2016-10-03 14:03:16 +0900158 // appService can be null if this activity is automatically recreated by the system
159 // with the saved instance state right after the phone process is killed.
160 if (appService == null) {
161 CatLog.d(LOG_TAG, "onCreate - appService is null");
162 finish();
163 return;
164 }
165
Yoshiaki Naka28313ba2017-08-04 12:20:53 +0900166 ActionBar actionBar = null;
167 if (getResources().getBoolean(R.bool.show_menu_title_only_on_menu)) {
168 actionBar = getActionBar();
169 if (actionBar != null) {
170 actionBar.hide();
171 }
172 }
Takanori Nakano48544352016-12-02 18:32:59 +0900173
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800174 // Set the layout for this activity.
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800175 setContentView(R.layout.stk_input);
176
Yoshiaki Naka28313ba2017-08-04 12:20:53 +0900177 if (actionBar != null) {
178 mMoreOptions = findViewById(R.id.more);
179 mMoreOptions.setVisibility(View.VISIBLE);
180 mMoreOptions.setOnClickListener(this);
181 }
182
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800183 // Initialize members
184 mTextIn = (EditText) this.findViewById(R.id.in_text);
185 mPromptView = (TextView) this.findViewById(R.id.prompt);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800186 // Set buttons listeners.
Wink Saville79085fc2009-06-09 10:27:23 -0700187 Button okButton = (Button) findViewById(R.id.button_ok);
Takanori Nakano260df9a2017-12-05 22:26:30 +0900188 Button cancelButton = (Button) findViewById(R.id.button_cancel);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800189 Button yesButton = (Button) findViewById(R.id.button_yes);
190 Button noButton = (Button) findViewById(R.id.button_no);
191
192 okButton.setOnClickListener(this);
Takanori Nakano260df9a2017-12-05 22:26:30 +0900193 cancelButton.setOnClickListener(this);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800194 yesButton.setOnClickListener(this);
195 noButton.setOnClickListener(this);
196
197 mYesNoLayout = findViewById(R.id.yes_no_layout);
198 mNormalLayout = findViewById(R.id.normal_layout);
Wink Savillee68857d2014-10-17 15:23:05 -0700199 initFromIntent(getIntent());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800200 }
201
202 @Override
203 protected void onPostCreate(Bundle savedInstanceState) {
204 super.onPostCreate(savedInstanceState);
205
206 mTextIn.addTextChangedListener(this);
207 }
208
209 @Override
210 public void onResume() {
211 super.onResume();
Wink Savillee68857d2014-10-17 15:23:05 -0700212 CatLog.d(LOG_TAG, "onResume - mIsResponseSent[" + mIsResponseSent +
213 "], slot id: " + mSlotId);
Yoshiaki Naka03a79d92018-08-09 18:41:31 +0900214 // If the terminal has already sent response to the card when this activity is resumed,
215 // keep this as a pending activity as this should be finished when the session ends.
216 if (!mIsResponseSent) {
217 setPendingState(false);
218 }
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +0900219
220 if (mAlarmTime == NO_INPUT_ALARM) {
221 startTimeOut();
222 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800223 }
224
225 @Override
226 public void onPause() {
227 super.onPause();
Wink Savillee68857d2014-10-17 15:23:05 -0700228 CatLog.d(LOG_TAG, "onPause - mIsResponseSent[" + mIsResponseSent + "]");
Yoshiaki Naka28313ba2017-08-04 12:20:53 +0900229 if (mPopupMenu != null) {
230 mPopupMenu.dismiss();
231 }
Wink Savillee68857d2014-10-17 15:23:05 -0700232 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800233
Wink Savillee68857d2014-10-17 15:23:05 -0700234 @Override
235 public void onStop() {
236 super.onStop();
237 CatLog.d(LOG_TAG, "onStop - mIsResponseSent[" + mIsResponseSent + "]");
Takanori Nakano1a672e62017-10-19 19:49:38 +0900238
Yoshiaki Naka03a79d92018-08-09 18:41:31 +0900239 // Nothing should be done here if this activity is being finished or restarted now.
240 if (isFinishing() || isChangingConfigurations()) {
Takanori Nakano1a672e62017-10-19 19:49:38 +0900241 return;
242 }
243
Yoshiaki Naka9de7afa2018-08-15 19:07:35 +0900244 if (mIsResponseSent) {
245 // It is unnecessary to keep this activity if the response was already sent and
246 // the dialog activity is NOT on the top of this activity.
247 if (!appService.isStkDialogActivated()) {
248 finish();
249 }
Wink Savillee68857d2014-10-17 15:23:05 -0700250 } else {
Yoshiaki Naka03a79d92018-08-09 18:41:31 +0900251 // This should be registered as the pending activity here
Yoshiaki Naka9de7afa2018-08-15 19:07:35 +0900252 // only when no response has been sent back to the card.
Yoshiaki Naka03a79d92018-08-09 18:41:31 +0900253 setPendingState(true);
Wink Savillee68857d2014-10-17 15:23:05 -0700254 }
255 }
256
257 @Override
258 public void onDestroy() {
259 super.onDestroy();
260 CatLog.d(LOG_TAG, "onDestroy - before Send End Session mIsResponseSent[" +
261 mIsResponseSent + " , " + mSlotId + "]");
Ryuto Sawadaba9b86b2016-10-03 14:03:16 +0900262 if (appService == null) {
263 return;
264 }
Takanori Nakano1a672e62017-10-19 19:49:38 +0900265 // Avoid sending the terminal response while the activty is being restarted
266 // due to some kind of configuration change.
267 if (!isChangingConfigurations()) {
268 // If the input activity is finished by stkappservice
269 // when receiving OP_LAUNCH_APP from the other SIM, we can not send TR here,
270 // since the input cmd is waiting user to process.
271 if (!mIsResponseSent && !appService.isInputPending(mSlotId)) {
272 CatLog.d(LOG_TAG, "handleDestroy - Send End Session");
273 sendResponse(StkAppService.RES_ID_END_SESSION);
274 }
Wink Savillee68857d2014-10-17 15:23:05 -0700275 }
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +0900276 cancelTimeOut();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800277 }
278
279 @Override
Yoshiaki Naka28313ba2017-08-04 12:20:53 +0900280 public void onConfigurationChanged(Configuration newConfig) {
281 super.onConfigurationChanged(newConfig);
282 if (mPopupMenu != null) {
283 mPopupMenu.dismiss();
284 }
285 }
286
287 @Override
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800288 public boolean onKeyDown(int keyCode, KeyEvent event) {
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +0900289 if (mIsResponseSent) {
290 CatLog.d(LOG_TAG, "Already responded");
Wink Savillee68857d2014-10-17 15:23:05 -0700291 return true;
292 }
293
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800294 switch (keyCode) {
295 case KeyEvent.KEYCODE_BACK:
Wink Savillee68857d2014-10-17 15:23:05 -0700296 CatLog.d(LOG_TAG, "onKeyDown - KEYCODE_BACK");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800297 sendResponse(StkAppService.RES_ID_BACKWARD, null, false);
Wink Savillee68857d2014-10-17 15:23:05 -0700298 return true;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800299 }
300 return super.onKeyDown(keyCode, event);
301 }
302
Wink Savillee68857d2014-10-17 15:23:05 -0700303 void sendResponse(int resId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800304 sendResponse(resId, null, false);
305 }
306
Wink Savillee68857d2014-10-17 15:23:05 -0700307 void sendResponse(int resId, String input, boolean help) {
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +0900308 cancelTimeOut();
309
Wink Savillee68857d2014-10-17 15:23:05 -0700310 if (mSlotId == -1) {
311 CatLog.d(LOG_TAG, "slot id is invalid");
312 return;
313 }
314
315 if (StkAppService.getInstance() == null) {
316 CatLog.d(LOG_TAG, "StkAppService is null, Ignore response: id is " + resId);
317 return;
318 }
319
Yoshiaki Naka28313ba2017-08-04 12:20:53 +0900320 if (mMoreOptions != null) {
321 mMoreOptions.setVisibility(View.INVISIBLE);
322 }
323
Cuihtlauac ALVARADObde7f032015-05-29 16:25:12 +0200324 CatLog.d(LOG_TAG, "sendResponse resID[" + resId + "] input[*****] help["
325 + help + "]");
Wink Savillee68857d2014-10-17 15:23:05 -0700326 mIsResponseSent = true;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800327 Bundle args = new Bundle();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800328 args.putInt(StkAppService.RES_ID, resId);
329 if (input != null) {
330 args.putString(StkAppService.INPUT, input);
331 }
332 args.putBoolean(StkAppService.HELP, help);
Takanori Nakano43dacc02018-07-26 11:27:39 +0900333 appService.sendResponse(args, mSlotId);
Yoshiaki Naka03a79d92018-08-09 18:41:31 +0900334
335 // This instance should be set as a pending activity and finished by the service
336 if (resId != StkAppService.RES_ID_END_SESSION) {
337 setPendingState(true);
338 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800339 }
340
341 @Override
342 public boolean onCreateOptionsMenu(android.view.Menu menu) {
343 super.onCreateOptionsMenu(menu);
Yoshiaki Naka28313ba2017-08-04 12:20:53 +0900344 createOptionsMenuInternal(menu);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800345 return true;
346 }
347
Yoshiaki Naka28313ba2017-08-04 12:20:53 +0900348 private void createOptionsMenuInternal(Menu menu) {
349 menu.add(Menu.NONE, StkApp.MENU_ID_END_SESSION, 1, R.string.menu_end_session);
350 menu.add(0, StkApp.MENU_ID_HELP, 2, R.string.help);
351 }
352
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800353 @Override
354 public boolean onPrepareOptionsMenu(android.view.Menu menu) {
355 super.onPrepareOptionsMenu(menu);
Yoshiaki Naka28313ba2017-08-04 12:20:53 +0900356 prepareOptionsMenuInternal(menu);
357 return true;
358 }
359
360 private void prepareOptionsMenuInternal(Menu menu) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800361 menu.findItem(StkApp.MENU_ID_END_SESSION).setVisible(true);
362 menu.findItem(StkApp.MENU_ID_HELP).setVisible(mStkInput.helpAvailable);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800363 }
364
365 @Override
366 public boolean onOptionsItemSelected(MenuItem item) {
Yoshiaki Naka28313ba2017-08-04 12:20:53 +0900367 if (optionsItemSelectedInternal(item)) {
368 return true;
369 }
370 return super.onOptionsItemSelected(item);
371 }
372
373 private boolean optionsItemSelectedInternal(MenuItem item) {
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +0900374 if (mIsResponseSent) {
375 CatLog.d(LOG_TAG, "Already responded");
Wink Savillee68857d2014-10-17 15:23:05 -0700376 return true;
377 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800378 switch (item.getItemId()) {
379 case StkApp.MENU_ID_END_SESSION:
380 sendResponse(StkAppService.RES_ID_END_SESSION);
381 finish();
382 return true;
383 case StkApp.MENU_ID_HELP:
384 sendResponse(StkAppService.RES_ID_INPUT, "", true);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800385 return true;
386 }
Yoshiaki Naka28313ba2017-08-04 12:20:53 +0900387 return false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800388 }
389
Wink Savillee68857d2014-10-17 15:23:05 -0700390 @Override
391 protected void onSaveInstanceState(Bundle outState) {
392 CatLog.d(LOG_TAG, "onSaveInstanceState: " + mSlotId);
Takanori Nakano1a672e62017-10-19 19:49:38 +0900393 outState.putBoolean(RESPONSE_SENT_KEY, mIsResponseSent);
394 outState.putString(INPUT_STRING_KEY, mTextIn.getText().toString());
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +0900395 outState.putLong(ALARM_TIME_KEY, mAlarmTime);
Yoshiaki Naka03a79d92018-08-09 18:41:31 +0900396 outState.putBoolean(PENDING, mIsPending);
Wink Savillee68857d2014-10-17 15:23:05 -0700397 }
398
399 @Override
400 protected void onRestoreInstanceState(Bundle savedInstanceState) {
401 CatLog.d(LOG_TAG, "onRestoreInstanceState: " + mSlotId);
Takanori Nakano1a672e62017-10-19 19:49:38 +0900402
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +0900403 mIsResponseSent = savedInstanceState.getBoolean(RESPONSE_SENT_KEY);
404 if (mIsResponseSent && (mMoreOptions != null)) {
Yoshiaki Naka28313ba2017-08-04 12:20:53 +0900405 mMoreOptions.setVisibility(View.INVISIBLE);
406 }
Takanori Nakano1a672e62017-10-19 19:49:38 +0900407
Takanori Nakano1a672e62017-10-19 19:49:38 +0900408 String savedString = savedInstanceState.getString(INPUT_STRING_KEY);
409 if (!TextUtils.isEmpty(savedString)) {
410 mTextIn.setText(savedString);
411 }
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +0900412
413 mAlarmTime = savedInstanceState.getLong(ALARM_TIME_KEY, NO_INPUT_ALARM);
414 if (mAlarmTime != NO_INPUT_ALARM) {
415 startTimeOut();
416 }
Yoshiaki Naka03a79d92018-08-09 18:41:31 +0900417
418 if (!mIsResponseSent && !savedInstanceState.getBoolean(PENDING)) {
419 // If this is in the foreground and no response has been sent to the card,
420 // this must not be registered as pending activity by the previous instance.
421 // No need to renew nor clear pending activity in this case.
422 } else {
423 // Renew the instance of the pending activity.
424 setPendingState(true);
425 }
426 }
427
428 private void setPendingState(boolean on) {
429 if (mIsPending != on) {
430 appService.getStkContext(mSlotId).setPendingActivityInstance(on ? this : null);
431 mIsPending = on;
432 }
Wink Savillee68857d2014-10-17 15:23:05 -0700433 }
434
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800435 public void beforeTextChanged(CharSequence s, int start, int count,
436 int after) {
437 }
438
439 public void onTextChanged(CharSequence s, int start, int before, int count) {
440 // Reset timeout.
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +0900441 cancelTimeOut();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800442 startTimeOut();
443 }
444
445 public void afterTextChanged(Editable s) {
446 }
447
448 private boolean verfiyTypedText() {
449 // If not enough input was typed in stay on the edit screen.
450 if (mTextIn.getText().length() < mStkInput.minLen) {
451 return false;
452 }
453
454 return true;
455 }
456
457 private void cancelTimeOut() {
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +0900458 if (mAlarmTime != NO_INPUT_ALARM) {
459 CatLog.d(LOG_TAG, "cancelTimeOut - slot id: " + mSlotId);
460 AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
461 am.cancel(mAlarmListener);
462 mAlarmTime = NO_INPUT_ALARM;
463 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800464 }
465
466 private void startTimeOut() {
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +0900467 // No need to set alarm if device sent TERMINAL RESPONSE already.
468 if (mIsResponseSent) {
469 return;
Abhishek Adappac7c3a462013-02-14 13:36:57 -0800470 }
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +0900471
472 if (mAlarmTime == NO_INPUT_ALARM) {
473 int duration = StkApp.calculateDurationInMilis(mStkInput.duration);
474 if (duration <= 0) {
475 duration = StkApp.UI_TIMEOUT;
476 }
477 mAlarmTime = SystemClock.elapsedRealtime() + duration;
478 }
479
480 CatLog.d(LOG_TAG, "startTimeOut: " + mAlarmTime + "ms, slot id: " + mSlotId);
481 AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
482 am.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, mAlarmTime, INPUT_ALARM_TAG,
483 mAlarmListener, null);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800484 }
485
486 private void configInputDisplay() {
487 TextView numOfCharsView = (TextView) findViewById(R.id.num_of_chars);
488 TextView inTypeView = (TextView) findViewById(R.id.input_type);
489
490 int inTypeId = R.string.alphabet;
491
492 // set the prompt.
Yoshiaki Nakadd0dbb12017-08-03 21:20:38 +0900493 if ((mStkInput.icon == null || !mStkInput.iconSelfExplanatory)
494 && !TextUtils.isEmpty(mStkInput.text)) {
Takeshi Shinoharac6589002013-05-27 11:01:06 +0900495 mPromptView.setText(mStkInput.text);
Yoshiaki Nakadd0dbb12017-08-03 21:20:38 +0900496 mPromptView.setVisibility(View.VISIBLE);
Takeshi Shinoharac6589002013-05-27 11:01:06 +0900497 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800498
Wink Saville79085fc2009-06-09 10:27:23 -0700499 // Set input type (alphabet/digit) info close to the InText form.
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800500 if (mStkInput.digitOnly) {
501 mTextIn.setKeyListener(StkDigitsKeyListener.getInstance());
502 inTypeId = R.string.digits;
503 }
504 inTypeView.setText(inTypeId);
505
Yoshiaki Naka28313ba2017-08-04 12:20:53 +0900506 setTitle(R.string.app_name);
Takanori Nakano48544352016-12-02 18:32:59 +0900507
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800508 if (mStkInput.icon != null) {
Yoshiaki Nakadd0dbb12017-08-03 21:20:38 +0900509 ImageView imageView = (ImageView) findViewById(R.id.icon);
Takanori Nakano48544352016-12-02 18:32:59 +0900510 imageView.setImageBitmap(mStkInput.icon);
511 imageView.setVisibility(View.VISIBLE);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800512 }
513
514 // Handle specific global and text attributes.
515 switch (mState) {
Wink Saville79085fc2009-06-09 10:27:23 -0700516 case STATE_TEXT:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800517 int maxLen = mStkInput.maxLen;
518 int minLen = mStkInput.minLen;
519 mTextIn.setFilters(new InputFilter[] {new InputFilter.LengthFilter(
520 maxLen)});
Wink Saville79085fc2009-06-09 10:27:23 -0700521
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800522 // Set number of chars info.
523 String lengthLimit = String.valueOf(minLen);
524 if (maxLen != minLen) {
525 lengthLimit = minLen + " - " + maxLen;
526 }
527 numOfCharsView.setText(lengthLimit);
528
529 if (!mStkInput.echo) {
Yujing Gu6b9716c2014-04-23 13:50:50 +0800530 mTextIn.setTransformationMethod(PasswordTransformationMethod
531 .getInstance());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800532 }
Srikanth Chintalaa091b732016-02-04 14:46:43 +0530533 mTextIn.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN);
Kazuhiro Uto12870912018-07-18 17:43:56 +0900534 // Request the initial focus on the edit box and show the software keyboard.
535 mTextIn.requestFocus();
536 getWindow().setSoftInputMode(
537 WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800538 // Set default text if present.
539 if (mStkInput.defaultText != null) {
540 mTextIn.setText(mStkInput.defaultText);
541 } else {
542 // make sure the text is cleared
543 mTextIn.setText("", BufferType.EDITABLE);
544 }
545
546 break;
547 case STATE_YES_NO:
548 // Set display mode - normal / yes-no layout
549 mYesNoLayout.setVisibility(View.VISIBLE);
550 mNormalLayout.setVisibility(View.GONE);
551 break;
552 }
553 }
554
Wink Savillee68857d2014-10-17 15:23:05 -0700555 private void initFromIntent(Intent intent) {
556 // Get the calling intent type: text/key, and setup the
557 // display parameters.
558 CatLog.d(LOG_TAG, "initFromIntent - slot id: " + mSlotId);
559 if (intent != null) {
560 mStkInput = intent.getParcelableExtra("INPUT");
561 mSlotId = intent.getIntExtra(StkAppService.SLOT_ID, -1);
562 CatLog.d(LOG_TAG, "onCreate - slot id: " + mSlotId);
563 if (mStkInput == null) {
564 finish();
565 } else {
566 mState = mStkInput.yesNo ? STATE_YES_NO :
567 STATE_TEXT;
568 configInputDisplay();
569 }
570 } else {
571 finish();
572 }
573 }
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +0900574
575 private final AlarmManager.OnAlarmListener mAlarmListener =
576 new AlarmManager.OnAlarmListener() {
577 @Override
578 public void onAlarm() {
579 CatLog.d(LOG_TAG, "The alarm time is reached");
580 mAlarmTime = NO_INPUT_ALARM;
Yoshiaki Nakaa95f5c82016-09-02 11:27:05 +0900581 sendResponse(StkAppService.RES_ID_TIMEOUT);
582 }
583 };
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800584}