blob: 7f4bd1be6fd1c8dad5ded8743878e0194b6da5da [file] [log] [blame]
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001/*
2 * Copyright (C) 2009 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.phone;
18
19import android.app.Activity;
20import android.app.Dialog;
21import android.app.ProgressDialog;
22import android.app.AlertDialog;
23import android.content.BroadcastReceiver;
24import android.content.ComponentName;
25import android.content.Context;
26import android.content.DialogInterface;
27import android.content.DialogInterface.OnDismissListener;
28import android.content.Intent;
29import android.content.IntentFilter;
30import android.content.ServiceConnection;
31import android.content.res.Resources;
32import android.os.AsyncResult;
33import android.os.Bundle;
34import android.os.CountDownTimer;
35import android.os.Handler;
36import android.os.IBinder;
37import android.os.Looper;
38import android.os.Message;
39import android.os.SystemProperties;
40import android.util.Log;
41
42import com.android.internal.telephony.Phone;
43import com.android.internal.telephony.TelephonyIntents;
44import com.android.internal.telephony.TelephonyProperties;
45
46/**
47 * Displays dialog that enables users to exit Emergency Callback Mode
48 *
49 * @see EmergencyCallbackModeService
50 */
51public class EmergencyCallbackModeExitDialog extends Activity implements OnDismissListener {
52
Yorke Lee34a72cb2014-10-12 13:17:04 -070053 private static final String TAG = "EmergencyCallbackMode";
54
Santos Cordon7d4ddf62013-07-10 11:58:08 -070055 /** Intent to trigger the Emergency Callback Mode exit dialog */
56 static final String ACTION_SHOW_ECM_EXIT_DIALOG =
57 "com.android.phone.action.ACTION_SHOW_ECM_EXIT_DIALOG";
58 /** Used to get the users choice from the return Intent's extra */
59 public static final String EXTRA_EXIT_ECM_RESULT = "exit_ecm_result";
60
61 public static final int EXIT_ECM_BLOCK_OTHERS = 1;
62 public static final int EXIT_ECM_DIALOG = 2;
63 public static final int EXIT_ECM_PROGRESS_DIALOG = 3;
64 public static final int EXIT_ECM_IN_EMERGENCY_CALL_DIALOG = 4;
65
66 AlertDialog mAlertDialog = null;
67 ProgressDialog mProgressDialog = null;
68 CountDownTimer mTimer = null;
69 EmergencyCallbackModeService mService = null;
70 Handler mHandler = null;
71 int mDialogType = 0;
72 long mEcmTimeout = 0;
73 private boolean mInEmergencyCall = false;
74 private static final int ECM_TIMER_RESET = 1;
75 private Phone mPhone = null;
76
77 @Override
78 public void onCreate(Bundle savedInstanceState) {
79 super.onCreate(savedInstanceState);
80
81 // Check if phone is in Emergency Callback Mode. If not, exit.
Yorke Lee34a72cb2014-10-12 13:17:04 -070082 final boolean isInEcm = Boolean.parseBoolean(
83 SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE));
84 Log.i(TAG, "ECMModeExitDialog launched - isInEcm: " + isInEcm);
85 if (!isInEcm) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -070086 finish();
Yorke Lee34a72cb2014-10-12 13:17:04 -070087 return;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070088 }
89
90 mHandler = new Handler();
91
92 // Start thread that will wait for the connection completion so that it can get
93 // timeout value from the service
94 Thread waitForConnectionCompleteThread = new Thread(null, mTask,
95 "EcmExitDialogWaitThread");
96 waitForConnectionCompleteThread.start();
97
98 // Register ECM timer reset notfication
99 mPhone = PhoneGlobals.getPhone();
100 mPhone.registerForEcmTimerReset(mTimerResetHandler, ECM_TIMER_RESET, null);
101
102 // Register receiver for intent closing the dialog
103 IntentFilter filter = new IntentFilter();
104 filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
105 registerReceiver(mEcmExitReceiver, filter);
106 }
107
108 @Override
109 public void onDestroy() {
110 super.onDestroy();
Yorke Lee34a72cb2014-10-12 13:17:04 -0700111 try {
112 unregisterReceiver(mEcmExitReceiver);
113 } catch (IllegalArgumentException e) {
114 // Receiver was never registered - silently ignore.
115 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700116 // Unregister ECM timer reset notification
Yorke Lee34a72cb2014-10-12 13:17:04 -0700117 if (mPhone != null) {
118 mPhone.unregisterForEcmTimerReset(mHandler);
119 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700120 }
121
122 @Override
123 protected void onRestoreInstanceState(Bundle savedInstanceState) {
124 super.onRestoreInstanceState(savedInstanceState);
125 mDialogType = savedInstanceState.getInt("DIALOG_TYPE");
126 }
127
128 @Override
129 protected void onSaveInstanceState(Bundle outState) {
130 super.onSaveInstanceState(outState);
131 outState.putInt("DIALOG_TYPE", mDialogType);
132 }
133
134 /**
135 * Waits until bind to the service completes
136 */
137 private Runnable mTask = new Runnable() {
138 public void run() {
139 Looper.prepare();
140
141 // Bind to the remote service
142 bindService(new Intent(EmergencyCallbackModeExitDialog.this,
143 EmergencyCallbackModeService.class), mConnection, Context.BIND_AUTO_CREATE);
144
145 // Wait for bind to finish
146 synchronized (EmergencyCallbackModeExitDialog.this) {
147 try {
148 if (mService == null) {
149 EmergencyCallbackModeExitDialog.this.wait();
150 }
151 } catch (InterruptedException e) {
152 Log.d("ECM", "EmergencyCallbackModeExitDialog InterruptedException: "
153 + e.getMessage());
154 e.printStackTrace();
155 }
156 }
157
158 // Get timeout value and call state from the service
159 if (mService != null) {
160 mEcmTimeout = mService.getEmergencyCallbackModeTimeout();
161 mInEmergencyCall = mService.getEmergencyCallbackModeCallState();
Yorke Lee34a72cb2014-10-12 13:17:04 -0700162 try {
163 // Unbind from remote service
164 unbindService(mConnection);
165 } catch (IllegalArgumentException e) {
166 // Failed to unbind from service. Don't crash as this brings down the entire
167 // radio.
168 Log.w(TAG, "Failed to unbind from EmergencyCallbackModeService");
169 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700170 }
171
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700172 // Show dialog
173 mHandler.post(new Runnable() {
174 public void run() {
175 showEmergencyCallbackModeExitDialog();
176 }
177 });
178 }
179 };
180
181 /**
182 * Shows Emergency Callback Mode dialog and starts countdown timer
183 */
184 private void showEmergencyCallbackModeExitDialog() {
Yorke Lee34a72cb2014-10-12 13:17:04 -0700185 if (!this.isResumed()) {
186 Log.w(TAG, "Tried to show dialog, but activity was already finished");
187 return;
188 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700189 if(mInEmergencyCall) {
190 mDialogType = EXIT_ECM_IN_EMERGENCY_CALL_DIALOG;
191 showDialog(EXIT_ECM_IN_EMERGENCY_CALL_DIALOG);
192 } else {
193 if (getIntent().getAction().equals(
194 TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS)) {
195 mDialogType = EXIT_ECM_BLOCK_OTHERS;
196 showDialog(EXIT_ECM_BLOCK_OTHERS);
197 } else if (getIntent().getAction().equals(ACTION_SHOW_ECM_EXIT_DIALOG)) {
198 mDialogType = EXIT_ECM_DIALOG;
199 showDialog(EXIT_ECM_DIALOG);
200 }
201
202 mTimer = new CountDownTimer(mEcmTimeout, 1000) {
203 @Override
204 public void onTick(long millisUntilFinished) {
205 CharSequence text = getDialogText(millisUntilFinished);
206 mAlertDialog.setMessage(text);
207 }
208
209 @Override
210 public void onFinish() {
211 //Do nothing
212 }
213 }.start();
214 }
215 }
216
217 /**
218 * Creates dialog that enables users to exit Emergency Callback Mode
219 */
220 @Override
221 protected Dialog onCreateDialog(int id) {
222 switch (id) {
223 case EXIT_ECM_BLOCK_OTHERS:
224 case EXIT_ECM_DIALOG:
225 CharSequence text = getDialogText(mEcmTimeout);
226 mAlertDialog = new AlertDialog.Builder(EmergencyCallbackModeExitDialog.this)
Tyler Gunn625eb0b2014-08-27 20:37:32 -0700227 .setIcon(R.drawable.ic_emergency_callback_mode)
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700228 .setTitle(R.string.phone_in_ecm_notification_title)
229 .setMessage(text)
230 .setPositiveButton(R.string.alert_dialog_yes,
231 new DialogInterface.OnClickListener() {
232 public void onClick(DialogInterface dialog,int whichButton) {
233 // User clicked Yes. Exit Emergency Callback Mode.
234 mPhone.exitEmergencyCallbackMode();
235
236 // Show progress dialog
237 showDialog(EXIT_ECM_PROGRESS_DIALOG);
238 mTimer.cancel();
239 }
240 })
241 .setNegativeButton(R.string.alert_dialog_no,
242 new DialogInterface.OnClickListener() {
243 public void onClick(DialogInterface dialog, int whichButton) {
244 // User clicked No
245 setResult(RESULT_OK, (new Intent()).putExtra(
246 EXTRA_EXIT_ECM_RESULT, false));
247 finish();
248 }
249 }).create();
250 mAlertDialog.setOnDismissListener(this);
251 return mAlertDialog;
252
253 case EXIT_ECM_IN_EMERGENCY_CALL_DIALOG:
254 mAlertDialog = new AlertDialog.Builder(EmergencyCallbackModeExitDialog.this)
Tyler Gunn625eb0b2014-08-27 20:37:32 -0700255 .setIcon(R.drawable.ic_emergency_callback_mode)
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700256 .setTitle(R.string.phone_in_ecm_notification_title)
257 .setMessage(R.string.alert_dialog_in_ecm_call)
258 .setNeutralButton(R.string.alert_dialog_dismiss,
259 new DialogInterface.OnClickListener() {
260 public void onClick(DialogInterface dialog, int whichButton) {
261 // User clicked Dismiss
262 setResult(RESULT_OK, (new Intent()).putExtra(
263 EXTRA_EXIT_ECM_RESULT, false));
264 finish();
265 }
266 }).create();
267 mAlertDialog.setOnDismissListener(this);
268 return mAlertDialog;
269
270 case EXIT_ECM_PROGRESS_DIALOG:
271 mProgressDialog = new ProgressDialog(EmergencyCallbackModeExitDialog.this);
272 mProgressDialog.setMessage(getText(R.string.progress_dialog_exiting_ecm));
273 mProgressDialog.setIndeterminate(true);
274 mProgressDialog.setCancelable(false);
275 return mProgressDialog;
276
277 default:
278 return null;
279 }
280 }
281
282 /**
283 * Returns dialog box text with updated timeout value
284 */
285 private CharSequence getDialogText(long millisUntilFinished) {
286 // Format time
287 int minutes = (int)(millisUntilFinished / 60000);
288 String time = String.format("%d:%02d", minutes,
289 (millisUntilFinished % 60000) / 1000);
290
291 switch (mDialogType) {
292 case EXIT_ECM_BLOCK_OTHERS:
293 return String.format(getResources().getQuantityText(
294 R.plurals.alert_dialog_not_avaialble_in_ecm, minutes).toString(), time);
295 case EXIT_ECM_DIALOG:
296 return String.format(getResources().getQuantityText(R.plurals.alert_dialog_exit_ecm,
297 minutes).toString(), time);
298 }
299 return null;
300 }
301
302 /**
303 * Closes activity when dialog is dismissed
304 */
Yorke Lee34a72cb2014-10-12 13:17:04 -0700305 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700306 public void onDismiss(DialogInterface dialog) {
307 EmergencyCallbackModeExitDialog.this.setResult(RESULT_OK, (new Intent())
308 .putExtra(EXTRA_EXIT_ECM_RESULT, false));
309 finish();
310 }
311
312 /**
313 * Listens for Emergency Callback Mode state change intents
314 */
315 private BroadcastReceiver mEcmExitReceiver = new BroadcastReceiver() {
316 @Override
317 public void onReceive(Context context, Intent intent) {
318 // Received exit Emergency Callback Mode notification close all dialogs
319 if (intent.getAction().equals(
320 TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
321 if (intent.getBooleanExtra("phoneinECMState", false) == false) {
322 if (mAlertDialog != null)
323 mAlertDialog.dismiss();
324 if (mProgressDialog != null)
325 mProgressDialog.dismiss();
326 EmergencyCallbackModeExitDialog.this.setResult(RESULT_OK, (new Intent())
327 .putExtra(EXTRA_EXIT_ECM_RESULT, true));
328 finish();
329 }
330 }
331 }
332 };
333
334 /**
335 * Class for interacting with the interface of the service
336 */
337 private ServiceConnection mConnection = new ServiceConnection() {
338 public void onServiceConnected(ComponentName className, IBinder service) {
339 mService = ((EmergencyCallbackModeService.LocalBinder)service).getService();
340 // Notify thread that connection is ready
341 synchronized (EmergencyCallbackModeExitDialog.this) {
342 EmergencyCallbackModeExitDialog.this.notify();
343 }
344 }
345
346 public void onServiceDisconnected(ComponentName className) {
347 mService = null;
348 }
349 };
350
351 /**
352 * Class for receiving framework timer reset notifications
353 */
354 private Handler mTimerResetHandler = new Handler () {
355 public void handleMessage(Message msg) {
356 switch (msg.what) {
357 case ECM_TIMER_RESET:
358 if(!((Boolean)((AsyncResult) msg.obj).result).booleanValue()) {
359 EmergencyCallbackModeExitDialog.this.setResult(RESULT_OK, (new Intent())
360 .putExtra(EXTRA_EXIT_ECM_RESULT, false));
361 finish();
362 }
363 break;
364 }
365 }
366 };
367}