• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.stk;
18 
19 import com.android.internal.telephony.cat.CatLog;
20 import com.android.internal.telephony.cat.TextMessage;
21 import com.android.internal.telephony.cat.CatLog;
22 
23 import android.app.Activity;
24 import android.app.AlarmManager;
25 import android.app.PendingIntent;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.content.BroadcastReceiver;
29 import android.content.Context;
30 import android.graphics.drawable.BitmapDrawable;
31 import android.os.Bundle;
32 import android.os.SystemClock;
33 import android.view.KeyEvent;
34 import android.view.View;
35 import android.view.Window;
36 import android.widget.Button;
37 import android.widget.TextView;
38 
39 /**
40  * AlertDialog used for DISPLAY TEXT commands.
41  *
42  */
43 public class StkDialogActivity extends Activity implements View.OnClickListener {
44     // members
45     private static final String className = new Object(){}.getClass().getEnclosingClass().getName();
46     private static final String LOG_TAG = className.substring(className.lastIndexOf('.') + 1);
47     TextMessage mTextMsg = null;
48     private int mSlotId = -1;
49     private StkAppService appService = StkAppService.getInstance();
50     // Determines whether Terminal Response (TR) has been sent
51     private boolean mIsResponseSent = false;
52     private Context mContext;
53     // Utilize AlarmManager for real-time countdown
54     private PendingIntent mTimeoutIntent;
55     private AlarmManager mAlarmManager;
56     private final static String ALARM_TIMEOUT = "com.android.stk.DIALOG_ALARM_TIMEOUT";
57 
58     //keys) for saving the state of the dialog in the icicle
59     private static final String TEXT = "text";
60 
61     // message id for time out
62     private static final int MSG_ID_TIMEOUT = 1;
63 
64     // buttons id
65     public static final int OK_BUTTON = R.id.button_ok;
66     public static final int CANCEL_BUTTON = R.id.button_cancel;
67 
68     @Override
onCreate(Bundle icicle)69     protected void onCreate(Bundle icicle) {
70         super.onCreate(icicle);
71 
72         CatLog.d(LOG_TAG, "onCreate, sim id: " + mSlotId);
73         // New Dialog is created - set to no response sent
74         mIsResponseSent = false;
75 
76         requestWindowFeature(Window.FEATURE_LEFT_ICON);
77 
78         setContentView(R.layout.stk_msg_dialog);
79 
80         Button okButton = (Button) findViewById(R.id.button_ok);
81         Button cancelButton = (Button) findViewById(R.id.button_cancel);
82 
83         okButton.setOnClickListener(this);
84         cancelButton.setOnClickListener(this);
85 
86         mContext = getBaseContext();
87         IntentFilter intentFilter = new IntentFilter();
88         intentFilter.addAction(ALARM_TIMEOUT);
89         mContext.registerReceiver(mBroadcastReceiver, intentFilter);
90         mAlarmManager =(AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
91 
92     }
93 
onClick(View v)94     public void onClick(View v) {
95         String input = null;
96         switch (v.getId()) {
97         case OK_BUTTON:
98             CatLog.d(LOG_TAG, "OK Clicked!, mSlotId: " + mSlotId);
99             cancelTimeOut();
100             sendResponse(StkAppService.RES_ID_CONFIRM, true);
101             break;
102         case CANCEL_BUTTON:
103             CatLog.d(LOG_TAG, "Cancel Clicked!, mSlotId: " + mSlotId);
104             cancelTimeOut();
105             sendResponse(StkAppService.RES_ID_CONFIRM, false);
106             break;
107         }
108         finish();
109     }
110 
111     @Override
onKeyDown(int keyCode, KeyEvent event)112     public boolean onKeyDown(int keyCode, KeyEvent event) {
113         switch (keyCode) {
114         case KeyEvent.KEYCODE_BACK:
115             CatLog.d(LOG_TAG, "onKeyDown - KEYCODE_BACK");
116             cancelTimeOut();
117             sendResponse(StkAppService.RES_ID_BACKWARD);
118             finish();
119             break;
120         }
121         return false;
122     }
123 
124     @Override
onResume()125     public void onResume() {
126         super.onResume();
127         CatLog.d(LOG_TAG, "onResume - mIsResponseSent[" + mIsResponseSent +
128                 "], sim id: " + mSlotId);
129 
130         initFromIntent(getIntent());
131         if (mTextMsg == null) {
132             finish();
133             return;
134         }
135 
136         Window window = getWindow();
137 
138         TextView mMessageView = (TextView) window
139                 .findViewById(R.id.dialog_message);
140 
141         setTitle(mTextMsg.title);
142 
143         if (!(mTextMsg.iconSelfExplanatory && mTextMsg.icon != null)) {
144             mMessageView.setText(mTextMsg.text);
145         }
146 
147         if (mTextMsg.icon == null) {
148             window.setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
149                     com.android.internal.R.drawable.stat_notify_sim_toolkit);
150         } else {
151             window.setFeatureDrawable(Window.FEATURE_LEFT_ICON,
152                     new BitmapDrawable(mTextMsg.icon));
153         }
154 
155         /*
156          * If the userClear flag is set and dialogduration is set to 0, the display Text
157          * should be displayed to user forever until some high priority event occurs
158          * (incoming call, MMI code execution etc as mentioned under section
159          * ETSI 102.223, 6.4.1)
160          */
161         if (StkApp.calculateDurationInMilis(mTextMsg.duration) == 0 &&
162             !mTextMsg.responseNeeded && mTextMsg.userClear) {
163             CatLog.d(LOG_TAG, "User should clear text..showing message forever");
164             return;
165         }
166 
167         appService.setDisplayTextDlgVisibility(true, mSlotId);
168 
169         /*
170          * When another activity takes the foreground, we do not want the Terminal
171          * Response timer to be restarted when our activity resumes. Hence we will
172          * check if there is an existing timer, and resume it. In this way we will
173          * inform the SIM in correct time when there is no response from the User
174          * to a dialog.
175          */
176         if (mTimeoutIntent != null) {
177             CatLog.d(LOG_TAG, "Pending Alarm! Let it finish counting down...");
178         }
179         else {
180             CatLog.d(LOG_TAG, "No Pending Alarm! OK to start timer...");
181             startTimeOut(mTextMsg.userClear);
182         }
183     }
184 
185     @Override
onPause()186     public void onPause() {
187         super.onPause();
188         CatLog.d(LOG_TAG, "onPause, sim id: " + mSlotId);
189         appService.setDisplayTextDlgVisibility(false, mSlotId);
190 
191         /*
192          * do not cancel the timer here cancelTimeOut(). If any higher/lower
193          * priority events such as incoming call, new sms, screen off intent,
194          * notification alerts, user actions such as 'User moving to another activtiy'
195          * etc.. occur during Display Text ongoing session,
196          * this activity would receive 'onPause()' event resulting in
197          * cancellation of the timer. As a result no terminal response is
198          * sent to the card.
199          */
200     }
201 
202     @Override
onStart()203     protected void onStart() {
204         CatLog.d(LOG_TAG, "onStart, sim id: " + mSlotId);
205         super.onStart();
206     }
207 
208     @Override
onStop()209     public void onStop() {
210         super.onStop();
211         CatLog.d(LOG_TAG, "onStop - before Send CONFIRM false mIsResponseSent[" +
212                 mIsResponseSent + "], sim id: " + mSlotId);
213         if (!mIsResponseSent) {
214             appService.getStkContext(mSlotId).setPendingDialogInstance(this);
215         } else {
216             CatLog.d(LOG_TAG, "finish.");
217             appService.getStkContext(mSlotId).setPendingDialogInstance(null);
218             cancelTimeOut();
219             finish();
220         }
221     }
222 
223     @Override
onDestroy()224     public void onDestroy() {
225         super.onDestroy();
226         CatLog.d(LOG_TAG, "onDestroy - mIsResponseSent[" + mIsResponseSent +
227                 "], sim id: " + mSlotId);
228         // if dialog activity is finished by stkappservice
229         // when receiving OP_LAUNCH_APP from the other SIM, we can not send TR here
230         // , since the dialog cmd is waiting user to process.
231         if (!mIsResponseSent && !appService.isDialogPending(mSlotId)) {
232             sendResponse(StkAppService.RES_ID_CONFIRM, false);
233         }
234         cancelTimeOut();
235         // Cleanup broadcast receivers to avoid leaks
236         if (mBroadcastReceiver != null) {
237             unregisterReceiver(mBroadcastReceiver);
238         }
239     }
240 
241     @Override
onSaveInstanceState(Bundle outState)242     public void onSaveInstanceState(Bundle outState) {
243         CatLog.d(LOG_TAG, "onSaveInstanceState");
244 
245         super.onSaveInstanceState(outState);
246 
247         outState.putParcelable(TEXT, mTextMsg);
248     }
249 
250     @Override
onRestoreInstanceState(Bundle savedInstanceState)251     public void onRestoreInstanceState(Bundle savedInstanceState) {
252         super.onRestoreInstanceState(savedInstanceState);
253 
254         mTextMsg = savedInstanceState.getParcelable(TEXT);
255         CatLog.d(LOG_TAG, "onRestoreInstanceState - [" + mTextMsg + "]");
256     }
257 
258     @Override
onNewIntent(Intent intent)259     protected void onNewIntent(Intent intent) {
260         CatLog.d(LOG_TAG, "onNewIntent - updating the same Dialog box");
261         setIntent(intent);
262     }
263 
sendResponse(int resId, boolean confirmed)264     private void sendResponse(int resId, boolean confirmed) {
265         if (mSlotId == -1) {
266             CatLog.d(LOG_TAG, "sim id is invalid");
267             return;
268         }
269 
270         if (StkAppService.getInstance() == null) {
271             CatLog.d(LOG_TAG, "Ignore response: id is " + resId);
272             return;
273         }
274 
275         CatLog.d(LOG_TAG, "sendResponse resID[" + resId + "] confirmed[" + confirmed + "]");
276 
277         if (mTextMsg.responseNeeded) {
278             Bundle args = new Bundle();
279             args.putInt(StkAppService.OPCODE, StkAppService.OP_RESPONSE);
280             args.putInt(StkAppService.SLOT_ID, mSlotId);
281             args.putInt(StkAppService.RES_ID, resId);
282             args.putBoolean(StkAppService.CONFIRMATION, confirmed);
283             startService(new Intent(this, StkAppService.class).putExtras(args));
284             mIsResponseSent = true;
285         }
286     }
287 
sendResponse(int resId)288     private void sendResponse(int resId) {
289         sendResponse(resId, true);
290     }
291 
initFromIntent(Intent intent)292     private void initFromIntent(Intent intent) {
293 
294         if (intent != null) {
295             mTextMsg = intent.getParcelableExtra("TEXT");
296             mSlotId = intent.getIntExtra(StkAppService.SLOT_ID, -1);
297         } else {
298             finish();
299         }
300 
301         CatLog.d(LOG_TAG, "initFromIntent - [" + mTextMsg + "], sim id: " + mSlotId);
302     }
303 
cancelTimeOut()304     private void cancelTimeOut() {
305         CatLog.d(LOG_TAG, "cancelTimeOut: " + mSlotId);
306         if (mTimeoutIntent != null) {
307             mAlarmManager.cancel(mTimeoutIntent);
308             mTimeoutIntent = null;
309         }
310     }
311 
startTimeOut(boolean waitForUserToClear)312     private void startTimeOut(boolean waitForUserToClear) {
313 
314         // Reset timeout.
315         cancelTimeOut();
316         int dialogDuration = StkApp.calculateDurationInMilis(mTextMsg.duration);
317         // If duration is specified, this has priority. If not, set timeout
318         // according to condition given by the card.
319         if (mTextMsg.userClear == true && mTextMsg.responseNeeded == false) {
320             return;
321         } else {
322             // userClear = false. will disappear after a while.
323             if (dialogDuration == 0) {
324                 if (waitForUserToClear) {
325                     dialogDuration = StkApp.DISP_TEXT_WAIT_FOR_USER_TIMEOUT;
326                 } else {
327                     dialogDuration = StkApp.DISP_TEXT_CLEAR_AFTER_DELAY_TIMEOUT;
328                 }
329             }
330             CatLog.d(LOG_TAG, "startTimeOut: " + mSlotId);
331             Intent mAlarmIntent = new Intent(ALARM_TIMEOUT);
332             mAlarmIntent.putExtra(StkAppService.SLOT_ID, mSlotId);
333             mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, mAlarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
334 
335             // Try to use a more stringent timer not affected by system sleep.
336             if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
337                 mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
338                     SystemClock.elapsedRealtime() + dialogDuration, mTimeoutIntent);
339             }
340             else {
341                 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
342                 SystemClock.elapsedRealtime() + dialogDuration, mTimeoutIntent);
343             }
344         }
345     }
346 
347     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
348         @Override public void onReceive(Context context, Intent intent) {
349             String action = intent.getAction();
350             int slotID = intent.getIntExtra(StkAppService.SLOT_ID, 0);
351 
352             if (action == null || slotID != mSlotId) return;
353             CatLog.d(LOG_TAG, "onReceive, action=" + action + ", sim id: " + slotID);
354             if (action.equals(ALARM_TIMEOUT)) {
355                 CatLog.d(LOG_TAG, "ALARM_TIMEOUT rcvd");
356                 mTimeoutIntent = null;
357                 sendResponse(StkAppService.RES_ID_TIMEOUT);
358                 finish();
359             }
360         }
361     };
362 }
363