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