Home | History | Annotate | Download | only in phone
      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
     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
    105     public void onDestroy() {
    106         super.onDestroy();
    107         unregisterReceiver(mEcmExitReceiver);
    108         // Unregister ECM timer reset notification
    109         mPhone.unregisterForEcmTimerReset(mHandler);
    110     }
    111 
    112     @Override
    113     protected void onRestoreInstanceState(Bundle savedInstanceState) {
    114         super.onRestoreInstanceState(savedInstanceState);
    115         mDialogType = savedInstanceState.getInt("DIALOG_TYPE");
    116     }
    117 
    118     @Override
    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      */
    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
    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      */
    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      */
    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