blob: d4bf37b05f3de5a70d2e4a73f2a710f1c719387d [file] [log] [blame]
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.phone;
import android.app.Activity;
import android.app.Application;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import android.telephony.ServiceState;
import android.view.WindowManager;
/**
* Helper class used by the InCallScreen to handle certain special
* cases when making an emergency call.
*
* Specifically, if the user tries to dial an emergency number but the
* radio is off, e.g. if the device is in airplane mode, this class is
* responsible for turning the radio back on and retrying the call.
*
* This class is initially launched using the same intent originally
* passed to the InCallScreen (presumably an ACTION_CALL_EMERGENCY intent)
* but with this class explicitly set as the className/component. Later,
* we retry the emergency call by firing off that same intent, with the
* component cleared, and using an integer extra called
* EMERGENCY_CALL_RETRY_KEY to convey information about the current state.
*/
public class EmergencyCallHandler extends Activity {
/** the key used to get the count from our Intent's extra(s) */
public static final String EMERGENCY_CALL_RETRY_KEY = "emergency_call_retry_count";
/** count indicating an initial attempt at the call should be made. */
public static final int INITIAL_ATTEMPT = -1;
/** number of times to retry the call and the time spent in between attempts*/
public static final int NUMBER_OF_RETRIES = 6;
public static final int TIME_BETWEEN_RETRIES_MS = 5000;
// constant events
private static final int EVENT_SERVICE_STATE_CHANGED = 100;
private static final int EVENT_TIMEOUT_EMERGENCY_CALL = 200;
/**
* Package holding information needed for the callback.
*/
private static class EmergencyCallInfo {
public Phone phone;
public Intent intent;
public ProgressDialog dialog;
public Application app;
}
/**
* static handler class, used to handle the two relevent events.
*/
private static EmergencyCallEventHandler sHandler;
private static class EmergencyCallEventHandler extends Handler {
public void handleMessage(Message msg) {
switch(msg.what) {
case EVENT_SERVICE_STATE_CHANGED: {
// make the initial call attempt after the radio is turned on.
ServiceState state = (ServiceState) ((AsyncResult) msg.obj).result;
if (state.getState() != ServiceState.STATE_POWER_OFF) {
EmergencyCallInfo eci =
(EmergencyCallInfo) ((AsyncResult) msg.obj).userObj;
// deregister for the service state change events.
eci.phone.unregisterForServiceStateChanged(this);
eci.app.startActivity(eci.intent);
eci.dialog.dismiss();
}
}
break;
case EVENT_TIMEOUT_EMERGENCY_CALL: {
// repeated call after the timeout period.
EmergencyCallInfo eci = (EmergencyCallInfo) msg.obj;
eci.app.startActivity(eci.intent);
eci.dialog.dismiss();
}
break;
}
}
}
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
// setup the phone and get the retry count embedded in the intent.
Phone phone = PhoneFactory.getDefaultPhone();
int retryCount = getIntent().getIntExtra(EMERGENCY_CALL_RETRY_KEY, INITIAL_ATTEMPT);
// create a new message object.
EmergencyCallInfo eci = new EmergencyCallInfo();
eci.phone = phone;
eci.app = getApplication();
eci.dialog = constructDialog(retryCount);
// The Intent we're going to fire off to retry the call is the
// same one that got us here (except that we *don't* explicitly
// specify this class as the component!)
eci.intent = getIntent().setComponent(null);
// And we'll be firing this Intent from the PhoneApp's context
// (see the startActivity() calls above) so the
// FLAG_ACTIVITY_NEW_TASK flag is required.
eci.intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// create the handler.
if (sHandler == null) {
sHandler = new EmergencyCallEventHandler();
}
// If this is the initial attempt, we need to register for a radio state
// change and turn the radio on. Otherwise, this is just a retry, and
// we simply wait the alloted time before sending the request to try
// the call again.
// Note: The radio logic ITSELF will try its best to put the emergency
// call through once the radio is turned on. The retry we have here
// is in case it fails; the current constants we have include making
// 6 attempts, with a 5 second delay between each.
if (retryCount == INITIAL_ATTEMPT) {
// place the number of pending retries in the intent.
eci.intent.putExtra(EMERGENCY_CALL_RETRY_KEY, NUMBER_OF_RETRIES);
// turn the radio on and listen for it to complete.
phone.registerForServiceStateChanged(sHandler,
EVENT_SERVICE_STATE_CHANGED, eci);
// If airplane mode is on, we turn it off the same way that the
// Settings activity turns it off.
if (Settings.System.getInt(getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, 0) > 0) {
// Change the system setting
Settings.System.putInt(getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0);
// Post the intent
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", false);
sendBroadcast(intent);
// Otherwise, for some strange reason the radio is just off, so
// we just turn it back on.
} else {
phone.setRadioPower(true);
}
} else {
// decrement and store the number of retries.
eci.intent.putExtra(EMERGENCY_CALL_RETRY_KEY, (retryCount - 1));
// get the message and attach the data, then wait the alloted
// time and send.
Message m = sHandler.obtainMessage(EVENT_TIMEOUT_EMERGENCY_CALL);
m.obj = eci;
sHandler.sendMessageDelayed(m, TIME_BETWEEN_RETRIES_MS);
}
finish();
}
/**
* create the dialog and hand it back to caller.
*/
private ProgressDialog constructDialog(int retryCount) {
// figure out the message to display.
int msgId = (retryCount == INITIAL_ATTEMPT) ?
R.string.emergency_enable_radio_dialog_message :
R.string.emergency_enable_radio_dialog_retry;
// create a system dialog that will persist outside this activity.
ProgressDialog pd = new ProgressDialog(getApplication());
pd.setTitle(getText(R.string.emergency_enable_radio_dialog_title));
pd.setMessage(getText(msgId));
pd.setIndeterminate(true);
pd.setCancelable(false);
pd.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
pd.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
// show the dialog
pd.show();
return pd;
}
}