blob: 3069edbd9fa8f4913721e9ab9d7da92cbe819787 [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 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
Wink Saville79085fc2009-06-09 10:27:23 -07007 *
The Android Open Source Project9d9730a2009-03-03 19:32:37 -08008 * 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;
21import android.content.Context;
22import android.content.Intent;
23import android.graphics.drawable.BitmapDrawable;
24import android.os.Bundle;
25import android.os.Handler;
26import android.os.Message;
27import android.text.Editable;
28import android.text.InputFilter;
duho.roee36b6f2013-09-03 15:15:16 +090029import android.text.InputType;
Yoshiaki Nakadd0dbb12017-08-03 21:20:38 +090030import android.text.TextUtils;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080031import android.text.TextWatcher;
32import android.text.method.PasswordTransformationMethod;
33import android.view.KeyEvent;
34import android.view.MenuItem;
35import android.view.View;
36import android.view.Window;
37import android.widget.Button;
Takanori Nakano48544352016-12-02 18:32:59 +090038import android.widget.ImageView;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080039import android.widget.TextView;
40import android.widget.EditText;
41import android.widget.TextView.BufferType;
Wink Savillee68857d2014-10-17 15:23:05 -070042import com.android.internal.telephony.cat.CatLog;
Alex Yakavenkad41f1d92010-07-12 14:13:13 -070043import com.android.internal.telephony.cat.FontSize;
44import com.android.internal.telephony.cat.Input;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080045
46/**
47 * Display a request for a text input a long with a text edit form.
48 */
49public class StkInputActivity extends Activity implements View.OnClickListener,
50 TextWatcher {
51
52 // Members
53 private int mState;
54 private Context mContext;
55 private EditText mTextIn = null;
56 private TextView mPromptView = null;
57 private View mYesNoLayout = null;
58 private View mNormalLayout = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080059
60 // Constants
Wink Savillee68857d2014-10-17 15:23:05 -070061 private static final String className = new Object(){}.getClass().getEnclosingClass().getName();
62 private static final String LOG_TAG = className.substring(className.lastIndexOf('.') + 1);
63
64 private Input mStkInput = null;
65 private boolean mAcceptUsersInput = true;
66 // Constants
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080067 private static final int STATE_TEXT = 1;
68 private static final int STATE_YES_NO = 2;
69
70 static final String YES_STR_RESPONSE = "YES";
71 static final String NO_STR_RESPONSE = "NO";
72
73 // Font size factor values.
74 static final float NORMAL_FONT_FACTOR = 1;
75 static final float LARGE_FONT_FACTOR = 2;
76 static final float SMALL_FONT_FACTOR = (1 / 2);
77
Wink Saville79085fc2009-06-09 10:27:23 -070078 // message id for time out
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080079 private static final int MSG_ID_TIMEOUT = 1;
Wink Savillee68857d2014-10-17 15:23:05 -070080 private StkAppService appService = StkAppService.getInstance();
81
82 private boolean mIsResponseSent = false;
83 private int mSlotId = -1;
84 Activity mInstance = null;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080085
86 Handler mTimeoutHandler = new Handler() {
87 @Override
88 public void handleMessage(Message msg) {
89 switch(msg.what) {
90 case MSG_ID_TIMEOUT:
Wink Savillee68857d2014-10-17 15:23:05 -070091 CatLog.d(LOG_TAG, "Msg timeout.");
92 mAcceptUsersInput = false;
93 appService.getStkContext(mSlotId).setPendingActivityInstance(mInstance);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080094 sendResponse(StkAppService.RES_ID_TIMEOUT);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -080095 break;
96 }
97 }
98 };
99
100 // Click listener to handle buttons press..
101 public void onClick(View v) {
102 String input = null;
Wink Savillee68857d2014-10-17 15:23:05 -0700103 if (!mAcceptUsersInput) {
104 CatLog.d(LOG_TAG, "mAcceptUsersInput:false");
105 return;
106 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800107
108 switch (v.getId()) {
109 case R.id.button_ok:
110 // Check that text entered is valid .
111 if (!verfiyTypedText()) {
Wink Savillee68857d2014-10-17 15:23:05 -0700112 CatLog.d(LOG_TAG, "handleClick, invalid text");
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800113 return;
114 }
Wink Savillee68857d2014-10-17 15:23:05 -0700115 mAcceptUsersInput = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800116 input = mTextIn.getText().toString();
117 break;
118 // Yes/No layout buttons.
119 case R.id.button_yes:
Wink Savillee68857d2014-10-17 15:23:05 -0700120 mAcceptUsersInput = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800121 input = YES_STR_RESPONSE;
122 break;
123 case R.id.button_no:
Wink Savillee68857d2014-10-17 15:23:05 -0700124 mAcceptUsersInput = false;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800125 input = NO_STR_RESPONSE;
126 break;
127 }
Wink Savillee68857d2014-10-17 15:23:05 -0700128 CatLog.d(LOG_TAG, "handleClick, ready to response");
Preeti Ahuja03be6672012-08-30 19:21:25 +0530129 cancelTimeOut();
Wink Savillee68857d2014-10-17 15:23:05 -0700130 appService.getStkContext(mSlotId).setPendingActivityInstance(this);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800131 sendResponse(StkAppService.RES_ID_INPUT, input, false);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800132 }
133
134 @Override
135 public void onCreate(Bundle icicle) {
136 super.onCreate(icicle);
137
Wink Savillee68857d2014-10-17 15:23:05 -0700138 CatLog.d(LOG_TAG, "onCreate - mIsResponseSent[" + mIsResponseSent + "]");
139
Ryuto Sawadaba9b86b2016-10-03 14:03:16 +0900140 // appService can be null if this activity is automatically recreated by the system
141 // with the saved instance state right after the phone process is killed.
142 if (appService == null) {
143 CatLog.d(LOG_TAG, "onCreate - appService is null");
144 finish();
145 return;
146 }
147
Takanori Nakano48544352016-12-02 18:32:59 +0900148 ActionBar actionBar = getActionBar();
149 actionBar.setCustomView(R.layout.stk_title);
150 actionBar.setDisplayShowCustomEnabled(true);
151
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800152 // Set the layout for this activity.
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800153 setContentView(R.layout.stk_input);
154
155 // Initialize members
156 mTextIn = (EditText) this.findViewById(R.id.in_text);
157 mPromptView = (TextView) this.findViewById(R.id.prompt);
Wink Savillee68857d2014-10-17 15:23:05 -0700158 mInstance = this;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800159 // Set buttons listeners.
Wink Saville79085fc2009-06-09 10:27:23 -0700160 Button okButton = (Button) findViewById(R.id.button_ok);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800161 Button yesButton = (Button) findViewById(R.id.button_yes);
162 Button noButton = (Button) findViewById(R.id.button_no);
163
164 okButton.setOnClickListener(this);
165 yesButton.setOnClickListener(this);
166 noButton.setOnClickListener(this);
167
168 mYesNoLayout = findViewById(R.id.yes_no_layout);
169 mNormalLayout = findViewById(R.id.normal_layout);
Wink Savillee68857d2014-10-17 15:23:05 -0700170 initFromIntent(getIntent());
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800171 mContext = getBaseContext();
Wink Savillee68857d2014-10-17 15:23:05 -0700172 mAcceptUsersInput = true;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800173 }
174
175 @Override
176 protected void onPostCreate(Bundle savedInstanceState) {
177 super.onPostCreate(savedInstanceState);
178
179 mTextIn.addTextChangedListener(this);
180 }
181
182 @Override
183 public void onResume() {
184 super.onResume();
Wink Savillee68857d2014-10-17 15:23:05 -0700185 CatLog.d(LOG_TAG, "onResume - mIsResponseSent[" + mIsResponseSent +
186 "], slot id: " + mSlotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800187 startTimeOut();
Wink Savillee68857d2014-10-17 15:23:05 -0700188 appService.getStkContext(mSlotId).setPendingActivityInstance(null);
hoonsung.parkcba29962015-07-06 23:17:38 +0900189 if (mIsResponseSent) {
190 cancelTimeOut();
191 finish();
192 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800193 }
194
195 @Override
196 public void onPause() {
197 super.onPause();
Wink Savillee68857d2014-10-17 15:23:05 -0700198 CatLog.d(LOG_TAG, "onPause - mIsResponseSent[" + mIsResponseSent + "]");
199 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800200
Wink Savillee68857d2014-10-17 15:23:05 -0700201 @Override
202 public void onStop() {
203 super.onStop();
204 CatLog.d(LOG_TAG, "onStop - mIsResponseSent[" + mIsResponseSent + "]");
205 if (mIsResponseSent) {
206 cancelTimeOut();
207 finish();
208 } else {
209 appService.getStkContext(mSlotId).setPendingActivityInstance(this);
210 }
211 }
212
213 @Override
214 public void onDestroy() {
215 super.onDestroy();
216 CatLog.d(LOG_TAG, "onDestroy - before Send End Session mIsResponseSent[" +
217 mIsResponseSent + " , " + mSlotId + "]");
Ryuto Sawadaba9b86b2016-10-03 14:03:16 +0900218 if (appService == null) {
219 return;
220 }
Wink Savillee68857d2014-10-17 15:23:05 -0700221 //If the input activity is finished by stkappservice
222 //when receiving OP_LAUNCH_APP from the other SIM, we can not send TR here
223 //, since the input cmd is waiting user to process.
224 if (!mIsResponseSent && !appService.isInputPending(mSlotId)) {
225 CatLog.d(LOG_TAG, "handleDestroy - Send End Session");
226 sendResponse(StkAppService.RES_ID_END_SESSION);
227 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800228 cancelTimeOut();
229 }
230
231 @Override
232 public boolean onKeyDown(int keyCode, KeyEvent event) {
Wink Savillee68857d2014-10-17 15:23:05 -0700233 if (!mAcceptUsersInput) {
234 CatLog.d(LOG_TAG, "mAcceptUsersInput:false");
235 return true;
236 }
237
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800238 switch (keyCode) {
239 case KeyEvent.KEYCODE_BACK:
Wink Savillee68857d2014-10-17 15:23:05 -0700240 CatLog.d(LOG_TAG, "onKeyDown - KEYCODE_BACK");
241 mAcceptUsersInput = false;
Preeti Ahuja03be6672012-08-30 19:21:25 +0530242 cancelTimeOut();
Wink Savillee68857d2014-10-17 15:23:05 -0700243 appService.getStkContext(mSlotId).setPendingActivityInstance(this);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800244 sendResponse(StkAppService.RES_ID_BACKWARD, null, false);
Wink Savillee68857d2014-10-17 15:23:05 -0700245 return true;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800246 }
247 return super.onKeyDown(keyCode, event);
248 }
249
Wink Savillee68857d2014-10-17 15:23:05 -0700250 void sendResponse(int resId) {
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800251 sendResponse(resId, null, false);
252 }
253
Wink Savillee68857d2014-10-17 15:23:05 -0700254 void sendResponse(int resId, String input, boolean help) {
255 if (mSlotId == -1) {
256 CatLog.d(LOG_TAG, "slot id is invalid");
257 return;
258 }
259
260 if (StkAppService.getInstance() == null) {
261 CatLog.d(LOG_TAG, "StkAppService is null, Ignore response: id is " + resId);
262 return;
263 }
264
Cuihtlauac ALVARADObde7f032015-05-29 16:25:12 +0200265 CatLog.d(LOG_TAG, "sendResponse resID[" + resId + "] input[*****] help["
266 + help + "]");
Wink Savillee68857d2014-10-17 15:23:05 -0700267 mIsResponseSent = true;
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800268 Bundle args = new Bundle();
269 args.putInt(StkAppService.OPCODE, StkAppService.OP_RESPONSE);
Wink Savillee68857d2014-10-17 15:23:05 -0700270 args.putInt(StkAppService.SLOT_ID, mSlotId);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800271 args.putInt(StkAppService.RES_ID, resId);
272 if (input != null) {
273 args.putString(StkAppService.INPUT, input);
274 }
275 args.putBoolean(StkAppService.HELP, help);
276 mContext.startService(new Intent(mContext, StkAppService.class)
277 .putExtras(args));
278 }
279
280 @Override
281 public boolean onCreateOptionsMenu(android.view.Menu menu) {
282 super.onCreateOptionsMenu(menu);
283 menu.add(android.view.Menu.NONE, StkApp.MENU_ID_END_SESSION, 1,
284 R.string.menu_end_session);
285 menu.add(0, StkApp.MENU_ID_HELP, 2, R.string.help);
286
287 return true;
288 }
289
290 @Override
291 public boolean onPrepareOptionsMenu(android.view.Menu menu) {
292 super.onPrepareOptionsMenu(menu);
293 menu.findItem(StkApp.MENU_ID_END_SESSION).setVisible(true);
294 menu.findItem(StkApp.MENU_ID_HELP).setVisible(mStkInput.helpAvailable);
295
296 return true;
297 }
298
299 @Override
300 public boolean onOptionsItemSelected(MenuItem item) {
Wink Savillee68857d2014-10-17 15:23:05 -0700301 if (!mAcceptUsersInput) {
302 CatLog.d(LOG_TAG, "mAcceptUsersInput:false");
303 return true;
304 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800305 switch (item.getItemId()) {
306 case StkApp.MENU_ID_END_SESSION:
Wink Savillee68857d2014-10-17 15:23:05 -0700307 mAcceptUsersInput = false;
308 cancelTimeOut();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800309 sendResponse(StkAppService.RES_ID_END_SESSION);
310 finish();
311 return true;
312 case StkApp.MENU_ID_HELP:
Wink Savillee68857d2014-10-17 15:23:05 -0700313 mAcceptUsersInput = false;
314 cancelTimeOut();
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800315 sendResponse(StkAppService.RES_ID_INPUT, "", true);
316 finish();
317 return true;
318 }
319 return super.onOptionsItemSelected(item);
320 }
321
Wink Savillee68857d2014-10-17 15:23:05 -0700322 @Override
323 protected void onSaveInstanceState(Bundle outState) {
324 CatLog.d(LOG_TAG, "onSaveInstanceState: " + mSlotId);
325 outState.putBoolean("ACCEPT_USERS_INPUT", mAcceptUsersInput);
326 }
327
328 @Override
329 protected void onRestoreInstanceState(Bundle savedInstanceState) {
330 CatLog.d(LOG_TAG, "onRestoreInstanceState: " + mSlotId);
331 mAcceptUsersInput = savedInstanceState.getBoolean("ACCEPT_USERS_INPUT");
332 }
333
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800334 public void beforeTextChanged(CharSequence s, int start, int count,
335 int after) {
336 }
337
338 public void onTextChanged(CharSequence s, int start, int before, int count) {
339 // Reset timeout.
340 startTimeOut();
341 }
342
343 public void afterTextChanged(Editable s) {
344 }
345
346 private boolean verfiyTypedText() {
347 // If not enough input was typed in stay on the edit screen.
348 if (mTextIn.getText().length() < mStkInput.minLen) {
349 return false;
350 }
351
352 return true;
353 }
354
355 private void cancelTimeOut() {
356 mTimeoutHandler.removeMessages(MSG_ID_TIMEOUT);
357 }
358
359 private void startTimeOut() {
Abhishek Adappac7c3a462013-02-14 13:36:57 -0800360 int duration = StkApp.calculateDurationInMilis(mStkInput.duration);
361
362 if (duration <= 0) {
363 duration = StkApp.UI_TIMEOUT;
364 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800365 cancelTimeOut();
366 mTimeoutHandler.sendMessageDelayed(mTimeoutHandler
Abhishek Adappac7c3a462013-02-14 13:36:57 -0800367 .obtainMessage(MSG_ID_TIMEOUT), duration);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800368 }
369
370 private void configInputDisplay() {
371 TextView numOfCharsView = (TextView) findViewById(R.id.num_of_chars);
372 TextView inTypeView = (TextView) findViewById(R.id.input_type);
373
374 int inTypeId = R.string.alphabet;
375
376 // set the prompt.
Yoshiaki Nakadd0dbb12017-08-03 21:20:38 +0900377 if ((mStkInput.icon == null || !mStkInput.iconSelfExplanatory)
378 && !TextUtils.isEmpty(mStkInput.text)) {
Takeshi Shinoharac6589002013-05-27 11:01:06 +0900379 mPromptView.setText(mStkInput.text);
Yoshiaki Nakadd0dbb12017-08-03 21:20:38 +0900380 mPromptView.setVisibility(View.VISIBLE);
Takeshi Shinoharac6589002013-05-27 11:01:06 +0900381 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800382
Wink Saville79085fc2009-06-09 10:27:23 -0700383 // Set input type (alphabet/digit) info close to the InText form.
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800384 if (mStkInput.digitOnly) {
385 mTextIn.setKeyListener(StkDigitsKeyListener.getInstance());
386 inTypeId = R.string.digits;
387 }
388 inTypeView.setText(inTypeId);
389
Takanori Nakano48544352016-12-02 18:32:59 +0900390 TextView textView = (TextView) this.findViewById(R.id.title_text);
391 textView.setText(R.string.app_name);
392
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800393 if (mStkInput.icon != null) {
Yoshiaki Nakadd0dbb12017-08-03 21:20:38 +0900394 ImageView imageView = (ImageView) findViewById(R.id.icon);
Takanori Nakano48544352016-12-02 18:32:59 +0900395 imageView.setImageBitmap(mStkInput.icon);
396 imageView.setVisibility(View.VISIBLE);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800397 }
398
399 // Handle specific global and text attributes.
400 switch (mState) {
Wink Saville79085fc2009-06-09 10:27:23 -0700401 case STATE_TEXT:
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800402 int maxLen = mStkInput.maxLen;
403 int minLen = mStkInput.minLen;
404 mTextIn.setFilters(new InputFilter[] {new InputFilter.LengthFilter(
405 maxLen)});
Wink Saville79085fc2009-06-09 10:27:23 -0700406
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800407 // Set number of chars info.
408 String lengthLimit = String.valueOf(minLen);
409 if (maxLen != minLen) {
410 lengthLimit = minLen + " - " + maxLen;
411 }
412 numOfCharsView.setText(lengthLimit);
413
414 if (!mStkInput.echo) {
duho.roee36b6f2013-09-03 15:15:16 +0900415 mTextIn.setInputType(InputType.TYPE_CLASS_NUMBER
416 | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800417 }
418 // Set default text if present.
419 if (mStkInput.defaultText != null) {
420 mTextIn.setText(mStkInput.defaultText);
421 } else {
422 // make sure the text is cleared
423 mTextIn.setText("", BufferType.EDITABLE);
424 }
425
426 break;
427 case STATE_YES_NO:
428 // Set display mode - normal / yes-no layout
429 mYesNoLayout.setVisibility(View.VISIBLE);
430 mNormalLayout.setVisibility(View.GONE);
431 break;
432 }
433 }
434
435 private float getFontSizeFactor(FontSize size) {
Wink Saville79085fc2009-06-09 10:27:23 -0700436 final float[] fontSizes =
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800437 {NORMAL_FONT_FACTOR, LARGE_FONT_FACTOR, SMALL_FONT_FACTOR};
438
439 return fontSizes[size.ordinal()];
440 }
Wink Savillee68857d2014-10-17 15:23:05 -0700441
442 private void initFromIntent(Intent intent) {
443 // Get the calling intent type: text/key, and setup the
444 // display parameters.
445 CatLog.d(LOG_TAG, "initFromIntent - slot id: " + mSlotId);
446 if (intent != null) {
447 mStkInput = intent.getParcelableExtra("INPUT");
448 mSlotId = intent.getIntExtra(StkAppService.SLOT_ID, -1);
449 CatLog.d(LOG_TAG, "onCreate - slot id: " + mSlotId);
450 if (mStkInput == null) {
451 finish();
452 } else {
453 mState = mStkInput.yesNo ? STATE_YES_NO :
454 STATE_TEXT;
455 configInputDisplay();
456 }
457 } else {
458 finish();
459 }
460 }
The Android Open Source Project9d9730a2009-03-03 19:32:37 -0800461}