blob: 07d518f220dfc8dc30d71b8a7a533f0daa910c50 [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
Sandeep Kuntade73a6a2014-10-15 18:45:56 +053081 mPhone = PhoneGlobals.getInstance().getPhoneInEcm();
Santos Cordon7d4ddf62013-07-10 11:58:08 -070082 // Check if phone is in Emergency Callback Mode. If not, exit.
Tyler Gunn00f0c432018-06-04 08:31:42 -070083 if (mPhone == null || !mPhone.isInEcm()) {
84 if (mPhone == null) {
85 android.util.EventLog.writeEvent(0x534e4554, "79995313", -1, "");
86 }
87 Log.i(TAG, "ECMModeExitDialog launched - isInEcm: false" + " phone:" + mPhone);
Santos Cordon7d4ddf62013-07-10 11:58:08 -070088 finish();
Yorke Lee34a72cb2014-10-12 13:17:04 -070089 return;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070090 }
91
92 mHandler = new Handler();
93
94 // Start thread that will wait for the connection completion so that it can get
95 // timeout value from the service
96 Thread waitForConnectionCompleteThread = new Thread(null, mTask,
97 "EcmExitDialogWaitThread");
98 waitForConnectionCompleteThread.start();
99
100 // Register ECM timer reset notfication
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700101 mPhone.registerForEcmTimerReset(mTimerResetHandler, ECM_TIMER_RESET, null);
102
103 // Register receiver for intent closing the dialog
104 IntentFilter filter = new IntentFilter();
105 filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
106 registerReceiver(mEcmExitReceiver, filter);
107 }
108
109 @Override
110 public void onDestroy() {
111 super.onDestroy();
Yorke Lee34a72cb2014-10-12 13:17:04 -0700112 try {
113 unregisterReceiver(mEcmExitReceiver);
114 } catch (IllegalArgumentException e) {
115 // Receiver was never registered - silently ignore.
116 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700117 // Unregister ECM timer reset notification
Yorke Lee34a72cb2014-10-12 13:17:04 -0700118 if (mPhone != null) {
119 mPhone.unregisterForEcmTimerReset(mHandler);
120 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700121 }
122
123 @Override
124 protected void onRestoreInstanceState(Bundle savedInstanceState) {
125 super.onRestoreInstanceState(savedInstanceState);
126 mDialogType = savedInstanceState.getInt("DIALOG_TYPE");
127 }
128
129 @Override
130 protected void onSaveInstanceState(Bundle outState) {
131 super.onSaveInstanceState(outState);
132 outState.putInt("DIALOG_TYPE", mDialogType);
133 }
134
135 /**
136 * Waits until bind to the service completes
137 */
138 private Runnable mTask = new Runnable() {
139 public void run() {
140 Looper.prepare();
141
142 // Bind to the remote service
143 bindService(new Intent(EmergencyCallbackModeExitDialog.this,
144 EmergencyCallbackModeService.class), mConnection, Context.BIND_AUTO_CREATE);
145
146 // Wait for bind to finish
147 synchronized (EmergencyCallbackModeExitDialog.this) {
148 try {
149 if (mService == null) {
150 EmergencyCallbackModeExitDialog.this.wait();
151 }
152 } catch (InterruptedException e) {
153 Log.d("ECM", "EmergencyCallbackModeExitDialog InterruptedException: "
154 + e.getMessage());
155 e.printStackTrace();
156 }
157 }
158
159 // Get timeout value and call state from the service
160 if (mService != null) {
161 mEcmTimeout = mService.getEmergencyCallbackModeTimeout();
162 mInEmergencyCall = mService.getEmergencyCallbackModeCallState();
Yorke Lee34a72cb2014-10-12 13:17:04 -0700163 try {
164 // Unbind from remote service
165 unbindService(mConnection);
166 } catch (IllegalArgumentException e) {
167 // Failed to unbind from service. Don't crash as this brings down the entire
168 // radio.
169 Log.w(TAG, "Failed to unbind from EmergencyCallbackModeService");
170 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700171 }
172
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700173 // Show dialog
174 mHandler.post(new Runnable() {
175 public void run() {
176 showEmergencyCallbackModeExitDialog();
177 }
178 });
179 }
180 };
181
182 /**
183 * Shows Emergency Callback Mode dialog and starts countdown timer
184 */
185 private void showEmergencyCallbackModeExitDialog() {
Yorke Lee34a72cb2014-10-12 13:17:04 -0700186 if (!this.isResumed()) {
187 Log.w(TAG, "Tried to show dialog, but activity was already finished");
188 return;
189 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700190 if(mInEmergencyCall) {
191 mDialogType = EXIT_ECM_IN_EMERGENCY_CALL_DIALOG;
192 showDialog(EXIT_ECM_IN_EMERGENCY_CALL_DIALOG);
193 } else {
194 if (getIntent().getAction().equals(
195 TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS)) {
196 mDialogType = EXIT_ECM_BLOCK_OTHERS;
197 showDialog(EXIT_ECM_BLOCK_OTHERS);
198 } else if (getIntent().getAction().equals(ACTION_SHOW_ECM_EXIT_DIALOG)) {
199 mDialogType = EXIT_ECM_DIALOG;
200 showDialog(EXIT_ECM_DIALOG);
201 }
202
203 mTimer = new CountDownTimer(mEcmTimeout, 1000) {
204 @Override
205 public void onTick(long millisUntilFinished) {
206 CharSequence text = getDialogText(millisUntilFinished);
207 mAlertDialog.setMessage(text);
208 }
209
210 @Override
211 public void onFinish() {
212 //Do nothing
213 }
214 }.start();
215 }
216 }
217
218 /**
219 * Creates dialog that enables users to exit Emergency Callback Mode
220 */
221 @Override
222 protected Dialog onCreateDialog(int id) {
223 switch (id) {
224 case EXIT_ECM_BLOCK_OTHERS:
225 case EXIT_ECM_DIALOG:
226 CharSequence text = getDialogText(mEcmTimeout);
227 mAlertDialog = new AlertDialog.Builder(EmergencyCallbackModeExitDialog.this)
Tyler Gunn625eb0b2014-08-27 20:37:32 -0700228 .setIcon(R.drawable.ic_emergency_callback_mode)
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700229 .setTitle(R.string.phone_in_ecm_notification_title)
230 .setMessage(text)
231 .setPositiveButton(R.string.alert_dialog_yes,
232 new DialogInterface.OnClickListener() {
233 public void onClick(DialogInterface dialog,int whichButton) {
234 // User clicked Yes. Exit Emergency Callback Mode.
235 mPhone.exitEmergencyCallbackMode();
236
237 // Show progress dialog
238 showDialog(EXIT_ECM_PROGRESS_DIALOG);
239 mTimer.cancel();
240 }
241 })
242 .setNegativeButton(R.string.alert_dialog_no,
243 new DialogInterface.OnClickListener() {
244 public void onClick(DialogInterface dialog, int whichButton) {
245 // User clicked No
246 setResult(RESULT_OK, (new Intent()).putExtra(
247 EXTRA_EXIT_ECM_RESULT, false));
248 finish();
249 }
250 }).create();
251 mAlertDialog.setOnDismissListener(this);
252 return mAlertDialog;
253
254 case EXIT_ECM_IN_EMERGENCY_CALL_DIALOG:
255 mAlertDialog = new AlertDialog.Builder(EmergencyCallbackModeExitDialog.this)
Tyler Gunn625eb0b2014-08-27 20:37:32 -0700256 .setIcon(R.drawable.ic_emergency_callback_mode)
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700257 .setTitle(R.string.phone_in_ecm_notification_title)
258 .setMessage(R.string.alert_dialog_in_ecm_call)
259 .setNeutralButton(R.string.alert_dialog_dismiss,
260 new DialogInterface.OnClickListener() {
261 public void onClick(DialogInterface dialog, int whichButton) {
262 // User clicked Dismiss
263 setResult(RESULT_OK, (new Intent()).putExtra(
264 EXTRA_EXIT_ECM_RESULT, false));
265 finish();
266 }
267 }).create();
268 mAlertDialog.setOnDismissListener(this);
269 return mAlertDialog;
270
271 case EXIT_ECM_PROGRESS_DIALOG:
272 mProgressDialog = new ProgressDialog(EmergencyCallbackModeExitDialog.this);
273 mProgressDialog.setMessage(getText(R.string.progress_dialog_exiting_ecm));
274 mProgressDialog.setIndeterminate(true);
275 mProgressDialog.setCancelable(false);
276 return mProgressDialog;
277
278 default:
279 return null;
280 }
281 }
282
283 /**
284 * Returns dialog box text with updated timeout value
285 */
286 private CharSequence getDialogText(long millisUntilFinished) {
287 // Format time
288 int minutes = (int)(millisUntilFinished / 60000);
289 String time = String.format("%d:%02d", minutes,
290 (millisUntilFinished % 60000) / 1000);
291
292 switch (mDialogType) {
293 case EXIT_ECM_BLOCK_OTHERS:
294 return String.format(getResources().getQuantityText(
295 R.plurals.alert_dialog_not_avaialble_in_ecm, minutes).toString(), time);
296 case EXIT_ECM_DIALOG:
297 return String.format(getResources().getQuantityText(R.plurals.alert_dialog_exit_ecm,
298 minutes).toString(), time);
299 }
300 return null;
301 }
302
303 /**
304 * Closes activity when dialog is dismissed
305 */
Yorke Lee34a72cb2014-10-12 13:17:04 -0700306 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700307 public void onDismiss(DialogInterface dialog) {
308 EmergencyCallbackModeExitDialog.this.setResult(RESULT_OK, (new Intent())
309 .putExtra(EXTRA_EXIT_ECM_RESULT, false));
310 finish();
311 }
312
313 /**
314 * Listens for Emergency Callback Mode state change intents
315 */
316 private BroadcastReceiver mEcmExitReceiver = new BroadcastReceiver() {
317 @Override
318 public void onReceive(Context context, Intent intent) {
319 // Received exit Emergency Callback Mode notification close all dialogs
320 if (intent.getAction().equals(
321 TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
322 if (intent.getBooleanExtra("phoneinECMState", false) == false) {
323 if (mAlertDialog != null)
324 mAlertDialog.dismiss();
325 if (mProgressDialog != null)
326 mProgressDialog.dismiss();
327 EmergencyCallbackModeExitDialog.this.setResult(RESULT_OK, (new Intent())
328 .putExtra(EXTRA_EXIT_ECM_RESULT, true));
329 finish();
330 }
331 }
332 }
333 };
334
335 /**
336 * Class for interacting with the interface of the service
337 */
338 private ServiceConnection mConnection = new ServiceConnection() {
339 public void onServiceConnected(ComponentName className, IBinder service) {
340 mService = ((EmergencyCallbackModeService.LocalBinder)service).getService();
341 // Notify thread that connection is ready
342 synchronized (EmergencyCallbackModeExitDialog.this) {
343 EmergencyCallbackModeExitDialog.this.notify();
344 }
345 }
346
347 public void onServiceDisconnected(ComponentName className) {
348 mService = null;
349 }
350 };
351
352 /**
353 * Class for receiving framework timer reset notifications
354 */
355 private Handler mTimerResetHandler = new Handler () {
356 public void handleMessage(Message msg) {
357 switch (msg.what) {
358 case ECM_TIMER_RESET:
359 if(!((Boolean)((AsyncResult) msg.obj).result).booleanValue()) {
360 EmergencyCallbackModeExitDialog.this.setResult(RESULT_OK, (new Intent())
361 .putExtra(EXTRA_EXIT_ECM_RESULT, false));
362 finish();
363 }
364 break;
365 }
366 }
367 };
368}