blob: dcfa024a56cb2884226a2a7a71126b96e4134cc3 [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;
Brad Ebinger6d4ef742018-02-07 10:59:33 -080020import android.app.AlertDialog;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070021import android.app.Dialog;
22import android.app.ProgressDialog;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070023import android.content.BroadcastReceiver;
24import android.content.ComponentName;
25import android.content.Context;
26import android.content.DialogInterface;
Li Wei65667ea2017-08-02 16:06:59 +080027import android.content.DialogInterface.OnCancelListener;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070028import android.content.Intent;
29import android.content.IntentFilter;
30import android.content.ServiceConnection;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070031import android.os.AsyncResult;
32import android.os.Bundle;
33import android.os.CountDownTimer;
34import android.os.Handler;
35import android.os.IBinder;
36import android.os.Looper;
37import android.os.Message;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070038import android.util.Log;
39
40import com.android.internal.telephony.Phone;
41import com.android.internal.telephony.TelephonyIntents;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070042
43/**
44 * Displays dialog that enables users to exit Emergency Callback Mode
45 *
46 * @see EmergencyCallbackModeService
47 */
Li Wei65667ea2017-08-02 16:06:59 +080048public class EmergencyCallbackModeExitDialog extends Activity implements OnCancelListener {
Santos Cordon7d4ddf62013-07-10 11:58:08 -070049
Yorke Lee34a72cb2014-10-12 13:17:04 -070050 private static final String TAG = "EmergencyCallbackMode";
51
Santos Cordon7d4ddf62013-07-10 11:58:08 -070052 /** Intent to trigger the Emergency Callback Mode exit dialog */
53 static final String ACTION_SHOW_ECM_EXIT_DIALOG =
54 "com.android.phone.action.ACTION_SHOW_ECM_EXIT_DIALOG";
Santos Cordon7d4ddf62013-07-10 11:58:08 -070055
56 public static final int EXIT_ECM_BLOCK_OTHERS = 1;
57 public static final int EXIT_ECM_DIALOG = 2;
58 public static final int EXIT_ECM_PROGRESS_DIALOG = 3;
59 public static final int EXIT_ECM_IN_EMERGENCY_CALL_DIALOG = 4;
60
61 AlertDialog mAlertDialog = null;
62 ProgressDialog mProgressDialog = null;
63 CountDownTimer mTimer = null;
64 EmergencyCallbackModeService mService = null;
65 Handler mHandler = null;
66 int mDialogType = 0;
67 long mEcmTimeout = 0;
68 private boolean mInEmergencyCall = false;
69 private static final int ECM_TIMER_RESET = 1;
70 private Phone mPhone = null;
Jordan Liu1cfab0d2019-09-27 11:17:52 -070071 private boolean mIsResumed = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070072
73 @Override
74 public void onCreate(Bundle savedInstanceState) {
75 super.onCreate(savedInstanceState);
76
Sandeep Kuntade73a6a2014-10-15 18:45:56 +053077 mPhone = PhoneGlobals.getInstance().getPhoneInEcm();
Santos Cordon7d4ddf62013-07-10 11:58:08 -070078 // Check if phone is in Emergency Callback Mode. If not, exit.
Brad Ebinger6d4ef742018-02-07 10:59:33 -080079 if (mPhone == null || !mPhone.isInEcm()) {
80 Log.i(TAG, "ECMModeExitDialog launched - isInEcm: false" + " phone:" + mPhone);
Santos Cordon7d4ddf62013-07-10 11:58:08 -070081 finish();
Yorke Lee34a72cb2014-10-12 13:17:04 -070082 return;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070083 }
Brad Ebinger6d4ef742018-02-07 10:59:33 -080084 Log.i(TAG, "ECMModeExitDialog launched - isInEcm: true" + " phone:" + mPhone);
Santos Cordon7d4ddf62013-07-10 11:58:08 -070085
86 mHandler = new Handler();
87
88 // Start thread that will wait for the connection completion so that it can get
89 // timeout value from the service
90 Thread waitForConnectionCompleteThread = new Thread(null, mTask,
91 "EcmExitDialogWaitThread");
92 waitForConnectionCompleteThread.start();
93
94 // Register ECM timer reset notfication
Santos Cordon7d4ddf62013-07-10 11:58:08 -070095 mPhone.registerForEcmTimerReset(mTimerResetHandler, ECM_TIMER_RESET, null);
96
97 // Register receiver for intent closing the dialog
98 IntentFilter filter = new IntentFilter();
99 filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
100 registerReceiver(mEcmExitReceiver, filter);
101 }
102
103 @Override
Jordan Liu1cfab0d2019-09-27 11:17:52 -0700104 public void onResume() {
105 super.onResume();
106 mIsResumed = true;
107 }
108
109 @Override
110 public void onPause() {
111 super.onPause();
112 mIsResumed = false;
113 }
114
115 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700116 public void onDestroy() {
117 super.onDestroy();
Yorke Lee34a72cb2014-10-12 13:17:04 -0700118 try {
119 unregisterReceiver(mEcmExitReceiver);
120 } catch (IllegalArgumentException e) {
121 // Receiver was never registered - silently ignore.
122 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700123 // Unregister ECM timer reset notification
Yorke Lee34a72cb2014-10-12 13:17:04 -0700124 if (mPhone != null) {
125 mPhone.unregisterForEcmTimerReset(mHandler);
126 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700127 }
128
129 @Override
130 protected void onRestoreInstanceState(Bundle savedInstanceState) {
131 super.onRestoreInstanceState(savedInstanceState);
132 mDialogType = savedInstanceState.getInt("DIALOG_TYPE");
133 }
134
135 @Override
136 protected void onSaveInstanceState(Bundle outState) {
137 super.onSaveInstanceState(outState);
138 outState.putInt("DIALOG_TYPE", mDialogType);
139 }
140
141 /**
142 * Waits until bind to the service completes
143 */
144 private Runnable mTask = new Runnable() {
145 public void run() {
146 Looper.prepare();
147
148 // Bind to the remote service
149 bindService(new Intent(EmergencyCallbackModeExitDialog.this,
150 EmergencyCallbackModeService.class), mConnection, Context.BIND_AUTO_CREATE);
151
152 // Wait for bind to finish
153 synchronized (EmergencyCallbackModeExitDialog.this) {
154 try {
155 if (mService == null) {
156 EmergencyCallbackModeExitDialog.this.wait();
157 }
158 } catch (InterruptedException e) {
159 Log.d("ECM", "EmergencyCallbackModeExitDialog InterruptedException: "
160 + e.getMessage());
161 e.printStackTrace();
162 }
163 }
164
165 // Get timeout value and call state from the service
166 if (mService != null) {
167 mEcmTimeout = mService.getEmergencyCallbackModeTimeout();
168 mInEmergencyCall = mService.getEmergencyCallbackModeCallState();
Yorke Lee34a72cb2014-10-12 13:17:04 -0700169 try {
170 // Unbind from remote service
171 unbindService(mConnection);
172 } catch (IllegalArgumentException e) {
173 // Failed to unbind from service. Don't crash as this brings down the entire
174 // radio.
175 Log.w(TAG, "Failed to unbind from EmergencyCallbackModeService");
176 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700177 }
178
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700179 // Show dialog
180 mHandler.post(new Runnable() {
181 public void run() {
182 showEmergencyCallbackModeExitDialog();
183 }
184 });
185 }
186 };
187
188 /**
189 * Shows Emergency Callback Mode dialog and starts countdown timer
190 */
191 private void showEmergencyCallbackModeExitDialog() {
Jordan Liu1cfab0d2019-09-27 11:17:52 -0700192 if (!mIsResumed) {
Yorke Lee34a72cb2014-10-12 13:17:04 -0700193 Log.w(TAG, "Tried to show dialog, but activity was already finished");
194 return;
195 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700196 if(mInEmergencyCall) {
197 mDialogType = EXIT_ECM_IN_EMERGENCY_CALL_DIALOG;
198 showDialog(EXIT_ECM_IN_EMERGENCY_CALL_DIALOG);
199 } else {
200 if (getIntent().getAction().equals(
201 TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS)) {
202 mDialogType = EXIT_ECM_BLOCK_OTHERS;
203 showDialog(EXIT_ECM_BLOCK_OTHERS);
204 } else if (getIntent().getAction().equals(ACTION_SHOW_ECM_EXIT_DIALOG)) {
205 mDialogType = EXIT_ECM_DIALOG;
206 showDialog(EXIT_ECM_DIALOG);
207 }
208
209 mTimer = new CountDownTimer(mEcmTimeout, 1000) {
210 @Override
211 public void onTick(long millisUntilFinished) {
212 CharSequence text = getDialogText(millisUntilFinished);
213 mAlertDialog.setMessage(text);
214 }
215
216 @Override
217 public void onFinish() {
218 //Do nothing
219 }
220 }.start();
221 }
222 }
223
224 /**
225 * Creates dialog that enables users to exit Emergency Callback Mode
226 */
227 @Override
228 protected Dialog onCreateDialog(int id) {
229 switch (id) {
230 case EXIT_ECM_BLOCK_OTHERS:
231 case EXIT_ECM_DIALOG:
232 CharSequence text = getDialogText(mEcmTimeout);
Brad Ebinger1a3fa362018-04-19 13:43:31 -0700233 mAlertDialog = new AlertDialog.Builder(EmergencyCallbackModeExitDialog.this,
234 android.R.style.Theme_DeviceDefault_Dialog_Alert)
Tyler Gunn625eb0b2014-08-27 20:37:32 -0700235 .setIcon(R.drawable.ic_emergency_callback_mode)
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700236 .setTitle(R.string.phone_in_ecm_notification_title)
237 .setMessage(text)
238 .setPositiveButton(R.string.alert_dialog_yes,
239 new DialogInterface.OnClickListener() {
240 public void onClick(DialogInterface dialog,int whichButton) {
241 // User clicked Yes. Exit Emergency Callback Mode.
242 mPhone.exitEmergencyCallbackMode();
243
244 // Show progress dialog
245 showDialog(EXIT_ECM_PROGRESS_DIALOG);
246 mTimer.cancel();
247 }
248 })
249 .setNegativeButton(R.string.alert_dialog_no,
250 new DialogInterface.OnClickListener() {
251 public void onClick(DialogInterface dialog, int whichButton) {
252 // User clicked No
Pengquan Meng252acb32018-10-11 17:16:25 -0700253 setResult(RESULT_CANCELED);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700254 finish();
255 }
256 }).create();
Li Wei65667ea2017-08-02 16:06:59 +0800257 mAlertDialog.setOnCancelListener(this);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700258 return mAlertDialog;
259
260 case EXIT_ECM_IN_EMERGENCY_CALL_DIALOG:
Brad Ebinger1a3fa362018-04-19 13:43:31 -0700261 mAlertDialog = new AlertDialog.Builder(EmergencyCallbackModeExitDialog.this,
262 android.R.style.Theme_DeviceDefault_Dialog_Alert)
Tyler Gunn625eb0b2014-08-27 20:37:32 -0700263 .setIcon(R.drawable.ic_emergency_callback_mode)
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700264 .setTitle(R.string.phone_in_ecm_notification_title)
265 .setMessage(R.string.alert_dialog_in_ecm_call)
266 .setNeutralButton(R.string.alert_dialog_dismiss,
267 new DialogInterface.OnClickListener() {
268 public void onClick(DialogInterface dialog, int whichButton) {
269 // User clicked Dismiss
Pengquan Meng252acb32018-10-11 17:16:25 -0700270 setResult(RESULT_CANCELED);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700271 finish();
272 }
273 }).create();
Li Wei65667ea2017-08-02 16:06:59 +0800274 mAlertDialog.setOnCancelListener(this);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700275 return mAlertDialog;
276
277 case EXIT_ECM_PROGRESS_DIALOG:
278 mProgressDialog = new ProgressDialog(EmergencyCallbackModeExitDialog.this);
279 mProgressDialog.setMessage(getText(R.string.progress_dialog_exiting_ecm));
280 mProgressDialog.setIndeterminate(true);
281 mProgressDialog.setCancelable(false);
282 return mProgressDialog;
283
284 default:
285 return null;
286 }
287 }
288
289 /**
290 * Returns dialog box text with updated timeout value
291 */
292 private CharSequence getDialogText(long millisUntilFinished) {
293 // Format time
294 int minutes = (int)(millisUntilFinished / 60000);
295 String time = String.format("%d:%02d", minutes,
296 (millisUntilFinished % 60000) / 1000);
297
298 switch (mDialogType) {
299 case EXIT_ECM_BLOCK_OTHERS:
300 return String.format(getResources().getQuantityText(
301 R.plurals.alert_dialog_not_avaialble_in_ecm, minutes).toString(), time);
302 case EXIT_ECM_DIALOG:
303 return String.format(getResources().getQuantityText(R.plurals.alert_dialog_exit_ecm,
304 minutes).toString(), time);
305 }
306 return null;
307 }
308
309 /**
Li Wei65667ea2017-08-02 16:06:59 +0800310 * Closes activity when dialog is canceled
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700311 */
Yorke Lee34a72cb2014-10-12 13:17:04 -0700312 @Override
Li Wei65667ea2017-08-02 16:06:59 +0800313 public void onCancel(DialogInterface dialog) {
Pengquan Meng252acb32018-10-11 17:16:25 -0700314 EmergencyCallbackModeExitDialog.this.setResult(RESULT_CANCELED);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700315 finish();
316 }
317
318 /**
319 * Listens for Emergency Callback Mode state change intents
320 */
321 private BroadcastReceiver mEcmExitReceiver = new BroadcastReceiver() {
322 @Override
323 public void onReceive(Context context, Intent intent) {
324 // Received exit Emergency Callback Mode notification close all dialogs
325 if (intent.getAction().equals(
326 TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
327 if (intent.getBooleanExtra("phoneinECMState", false) == false) {
328 if (mAlertDialog != null)
329 mAlertDialog.dismiss();
330 if (mProgressDialog != null)
331 mProgressDialog.dismiss();
Pengquan Meng252acb32018-10-11 17:16:25 -0700332 EmergencyCallbackModeExitDialog.this.setResult(RESULT_OK);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700333 finish();
334 }
335 }
336 }
337 };
338
339 /**
340 * Class for interacting with the interface of the service
341 */
342 private ServiceConnection mConnection = new ServiceConnection() {
343 public void onServiceConnected(ComponentName className, IBinder service) {
344 mService = ((EmergencyCallbackModeService.LocalBinder)service).getService();
345 // Notify thread that connection is ready
346 synchronized (EmergencyCallbackModeExitDialog.this) {
347 EmergencyCallbackModeExitDialog.this.notify();
348 }
349 }
350
351 public void onServiceDisconnected(ComponentName className) {
352 mService = null;
353 }
354 };
355
356 /**
357 * Class for receiving framework timer reset notifications
358 */
359 private Handler mTimerResetHandler = new Handler () {
360 public void handleMessage(Message msg) {
361 switch (msg.what) {
362 case ECM_TIMER_RESET:
363 if(!((Boolean)((AsyncResult) msg.obj).result).booleanValue()) {
Pengquan Meng252acb32018-10-11 17:16:25 -0700364 EmergencyCallbackModeExitDialog.this.setResult(RESULT_CANCELED);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700365 finish();
366 }
367 break;
368 }
369 }
370 };
371}