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