Merge change 21754 into eclair

* changes:
  E911 call fix in ECM
This commit is contained in:
Android (Google) Code Review
2009-08-18 12:12:27 -07:00
5 changed files with 158 additions and 30 deletions

View File

@@ -433,6 +433,20 @@ public interface Phone {
*/
void unregisterForMmiComplete(Handler h);
/**
* Registration point for Ecm timer reset
* @param h handler to notify
* @param what user-defined message code
* @param obj placed in Message.obj
*/
public void registerForEcmTimerReset(Handler h, int what, Object obj);
/**
* Unregister for notification for Ecm timer reset
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForEcmTimerReset(Handler h);
/**
* Returns a list of MMI codes that are pending. (They have initiated
* but have not yet completed).

View File

@@ -760,6 +760,16 @@ public abstract class PhoneBase implements Phone {
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
}
public void registerForEcmTimerReset(Handler h, int what, Object obj) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
}
public void unregisterForEcmTimerReset(Handler h) {
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
}
public void registerForSignalInfo(Handler h, int what, Object obj) {
mCM.registerForSignalInfo(h, what, obj);
}

View File

@@ -323,6 +323,14 @@ public class PhoneProxy extends Handler implements Phone {
mActivePhone.unregisterForSubscriptionInfoReady(h);
}
public void registerForEcmTimerReset(Handler h, int what, Object obj) {
mActivePhone.registerForEcmTimerReset(h,what,obj);
}
public void unregisterForEcmTimerReset(Handler h) {
mActivePhone.unregisterForEcmTimerReset(h);
}
public boolean getIccRecordsLoaded() {
return mActivePhone.getIccRecordsLoaded();
}

View File

@@ -28,6 +28,8 @@ import android.os.AsyncResult;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.Registrant;
import android.os.RegistrantList;
import android.os.RemoteException;
@@ -72,8 +74,7 @@ import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OP
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -87,10 +88,14 @@ public class CDMAPhone extends PhoneBase {
// Default Emergency Callback Mode exit timer
private static final int DEFAULT_ECM_EXIT_TIMER_VALUE = 300000;
static final String VM_COUNT_CDMA = "vm_count_key_cdma";
private static final String VM_NUMBER_CDMA = "vm_number_key_cdma";
private String mVmNumber = null;
static final int RESTART_ECM_TIMER = 0; // restart Ecm timer
static final int CANCEL_ECM_TIMER = 1; // cancel Ecm timer
//***** Instance Variables
CdmaCallTracker mCT;
CdmaSMSDispatcher mSMS;
@@ -103,6 +108,7 @@ public class CDMAPhone extends PhoneBase {
RuimSmsInterfaceManager mRuimSmsInterfaceManager;
PhoneSubInfo mSubInfo;
EriManager mEriManager;
WakeLock mWakeLock;
// mNvLoadedRegistrants are informed after the EVENT_NV_READY
private RegistrantList mNvLoadedRegistrants = new RegistrantList();
@@ -110,17 +116,20 @@ public class CDMAPhone extends PhoneBase {
// mEriFileLoadedRegistrants are informed after the ERI text has been loaded
private RegistrantList mEriFileLoadedRegistrants = new RegistrantList();
// mECMExitRespRegistrant is informed after the phone has been exited
// mEcmTimerResetRegistrants are informed after Ecm timer is canceled or re-started
private RegistrantList mEcmTimerResetRegistrants = new RegistrantList();
// mEcmExitRespRegistrant is informed after the phone has been exited
//the emergency callback mode
//keep track of if phone is in emergency callback mode
private boolean mIsPhoneInECMState;
private Registrant mECMExitRespRegistrant;
private boolean mIsPhoneInEcmState;
private Registrant mEcmExitRespRegistrant;
private String mEsn;
private String mMeid;
// string to define how the carrier specifies its own ota sp number
private String mCarrierOtaSpNumSchema;
// A runnable which is used to automatically exit from ECM after a period of time.
// A runnable which is used to automatically exit from Ecm after a period of time.
private Runnable mExitEcmRunnable = new Runnable() {
public void run() {
exitEmergencyCallbackMode();
@@ -165,6 +174,9 @@ public class CDMAPhone extends PhoneBase {
mCM.registerForNVReady(h, EVENT_NV_READY, null);
mCM.setEmergencyCallbackMode(h, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null);
PowerManager pm
= (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,LOG_TAG);
//Change the system setting
SystemProperties.set(TelephonyProperties.CURRENT_ACTIVE_PHONE,
@@ -172,7 +184,7 @@ public class CDMAPhone extends PhoneBase {
// This is needed to handle phone process crashes
String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
mIsPhoneInECMState = inEcm.equals("true");
mIsPhoneInEcmState = inEcm.equals("true");
// get the string that specifies the carrier OTA Sp number
mCarrierOtaSpNumSchema = SystemProperties.get(
@@ -244,6 +256,10 @@ public class CDMAPhone extends PhoneBase {
protected void finalize() {
if(DBG) Log.d(LOG_TAG, "CDMAPhone finalized");
if (mWakeLock.isHeld()) {
Log.e(LOG_TAG, "UNEXPECTED; mWakeLock is held when finalizing.");
mWakeLock.release();
}
}
@@ -525,11 +541,11 @@ public class CDMAPhone extends PhoneBase {
}
public void setOnEcbModeExitResponse(Handler h, int what, Object obj) {
mECMExitRespRegistrant = new Registrant (h, what, obj);
mEcmExitRespRegistrant = new Registrant (h, what, obj);
}
public void unsetOnEcbModeExitResponse(Handler h) {
mECMExitRespRegistrant.clear();
mEcmExitRespRegistrant.clear();
}
public void registerForCallWaiting(Handler h, int what, Object obj) {
@@ -729,7 +745,7 @@ public class CDMAPhone extends PhoneBase {
public boolean enableDataConnectivity() {
// block data activities when phone is in emergency callback mode
if (mIsPhoneInECMState) {
if (mIsPhoneInEcmState) {
Intent intent = new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS);
ActivityManagerNative.broadcastStickyIntent(intent, null);
return false;
@@ -826,8 +842,9 @@ public class CDMAPhone extends PhoneBase {
void sendEmergencyCallbackModeChange(){
//Send an Intent
Intent intent = new Intent(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
intent.putExtra(PHONE_IN_ECM_STATE, mIsPhoneInECMState);
intent.putExtra(PHONE_IN_ECM_STATE, mIsPhoneInEcmState);
ActivityManagerNative.broadcastStickyIntent(intent,null);
if (DBG) Log.d(LOG_TAG, "sendEmergencyCallbackModeChange");
}
/*package*/ void
@@ -859,15 +876,21 @@ public class CDMAPhone extends PhoneBase {
@Override
public void exitEmergencyCallbackMode() {
if (mWakeLock.isHeld()) {
mWakeLock.release();
}
// Send a message which will invoke handleExitEmergencyCallbackMode
mCM.exitEmergencyCallbackMode(h.obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE));
}
private void handleEnterEmergencyCallbackMode(Message msg) {
Log.d(LOG_TAG, "Event EVENT_EMERGENCY_CALLBACK_MODE Received");
// if phone is not in ECM mode, and it's changed to ECM mode
if (mIsPhoneInECMState == false) {
mIsPhoneInECMState = true;
if (DBG) {
Log.d(LOG_TAG, "handleEnterEmergencyCallbackMode,mIsPhoneInEcmState= "
+ mIsPhoneInEcmState);
}
// if phone is not in Ecm mode, and it's changed to Ecm mode
if (mIsPhoneInEcmState == false) {
mIsPhoneInEcmState = true;
// notify change
sendEmergencyCallbackModeChange();
setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, "true");
@@ -877,23 +900,27 @@ public class CDMAPhone extends PhoneBase {
long delayInMillis = SystemProperties.getLong(
TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
h.postDelayed(mExitEcmRunnable, delayInMillis);
// We don't want to go to sleep while in Ecm
mWakeLock.acquire();
}
}
private void handleExitEmergencyCallbackMode(Message msg) {
Log.d(LOG_TAG, "Event EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE Received");
AsyncResult ar = (AsyncResult)msg.obj;
// Remove pending exit ECM runnable, if any
if (DBG) {
Log.d(LOG_TAG, "handleExitEmergencyCallbackMode,ar.exception , mIsPhoneInEcmState "
+ ar.exception + mIsPhoneInEcmState);
}
// Remove pending exit Ecm runnable, if any
h.removeCallbacks(mExitEcmRunnable);
if (mECMExitRespRegistrant != null) {
mECMExitRespRegistrant.notifyRegistrant(ar);
if (mEcmExitRespRegistrant != null) {
mEcmExitRespRegistrant.notifyRegistrant(ar);
}
// if exiting ecm success
if (ar.exception == null) {
if (mIsPhoneInECMState) {
mIsPhoneInECMState = false;
if (mIsPhoneInEcmState) {
mIsPhoneInEcmState = false;
setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, "false");
}
// send an Intent
@@ -903,6 +930,42 @@ public class CDMAPhone extends PhoneBase {
}
}
/**
* Handle to cancel or restart Ecm timer in emergency call back mode
* if action is CANCEL_ECM_TIMER, cancel Ecm timer and notify apps the timer is canceled;
* otherwise, restart Ecm timer and notify apps the timer is restarted.
*/
void handleTimerInEmergencyCallbackMode(int action) {
switch(action) {
case CANCEL_ECM_TIMER:
h.removeCallbacks(mExitEcmRunnable);
mEcmTimerResetRegistrants.notifyResult(new Boolean(true));
break;
case RESTART_ECM_TIMER:
long delayInMillis = SystemProperties.getLong(
TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
h.postDelayed(mExitEcmRunnable, delayInMillis);
mEcmTimerResetRegistrants.notifyResult(new Boolean(false));
break;
default:
Log.e(LOG_TAG, "handleTimerInEmergencyCallbackMode, unsupported action " + action);
}
}
/**
* Registration point for Ecm timer reset
* @param h handler to notify
* @param what User-defined message code
* @param obj placed in Message.obj
*/
public void registerForEcmTimerReset(Handler h, int what, Object obj) {
mEcmTimerResetRegistrants.addUnique(h, what, obj);
}
public void unregisterForEcmTimerReset(Handler h) {
mEcmTimerResetRegistrants.remove(h);
}
//***** Inner Classes
class MyHandler extends Handler {
MyHandler() {

View File

@@ -72,7 +72,7 @@ public final class CdmaCallTracker extends CallTracker {
CdmaConnection pendingMO;
boolean hangupPendingMO;
boolean pendingCallInECM=false;
boolean pendingCallInEcm=false;
CDMAPhone phone;
boolean desiredMute = false; // false = mute off
@@ -80,6 +80,7 @@ public final class CdmaCallTracker extends CallTracker {
int pendingCallClirMode;
Phone.State state = Phone.State.IDLE;
private boolean mIsEcmTimerCanceled = false;
// boolean needsPoll;
@@ -182,6 +183,14 @@ public final class CdmaCallTracker extends CallTracker {
throw new CallStateException("cannot dial in current state");
}
String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
boolean isPhoneInEcmMode = inEcm.equals("true");
boolean isEmergencyCall = PhoneNumberUtils.isEmergencyNumber(dialString);
// Cancel Ecm timer if a second emergency call is originating in Ecm mode
if (isPhoneInEcmMode && isEmergencyCall) {
handleEcmTimer(phone.CANCEL_ECM_TIMER);
}
// We are initiating a call therefore even if we previously
// didn't know the state (i.e. Generic was true) we now know
@@ -210,14 +219,14 @@ public final class CdmaCallTracker extends CallTracker {
// Always unmute when initiating a new call
setMute(false);
String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
if(inEcm.equals("false")) {
// In Ecm mode, if another emergency call is dialed, Ecm mode will not exit.
if(!isPhoneInEcmMode || (isPhoneInEcmMode && isEmergencyCall)) {
cm.dial(pendingMO.address, clirMode, obtainCompleteMessage());
} else {
phone.exitEmergencyCallbackMode();
phone.setOnEcbModeExitResponse(this,EVENT_EXIT_ECM_RESPONSE_CDMA, null);
pendingCallClirMode=clirMode;
pendingCallInECM=true;
pendingCallInEcm=true;
}
}
@@ -479,6 +488,11 @@ public final class CdmaCallTracker extends CallTracker {
// Someone has already asked to hangup this call
if (hangupPendingMO) {
hangupPendingMO = false;
// Re-start Ecm timer when an uncompleted emergency call ends
if (mIsEcmTimerCanceled) {
handleEcmTimer(phone.RESTART_ECM_TIMER);
}
try {
if (Phone.DEBUG_PHONE) log(
"poll: hangupPendingMO, hangup conn " + i);
@@ -532,6 +546,12 @@ public final class CdmaCallTracker extends CallTracker {
}
}
foregroundCall.setGeneric(false);
// Re-start Ecm timer when the connected emergency call ends
if (mIsEcmTimerCanceled) {
handleEcmTimer(phone.RESTART_ECM_TIMER);
}
// Dropped connections are removed from the CallTracker
// list but kept in the Call list
connections[i] = null;
@@ -571,8 +591,8 @@ public final class CdmaCallTracker extends CallTracker {
droppedDuringPoll.add(pendingMO);
pendingMO = null;
hangupPendingMO = false;
if( pendingCallInECM) {
pendingCallInECM = false;
if( pendingCallInEcm) {
pendingCallInEcm = false;
}
}
@@ -941,9 +961,9 @@ public final class CdmaCallTracker extends CallTracker {
case EVENT_EXIT_ECM_RESPONSE_CDMA:
//no matter the result, we still do the same here
if (pendingCallInECM) {
if (pendingCallInEcm) {
cm.dial(pendingMO.address, pendingCallClirMode, obtainCompleteMessage());
pendingCallInECM = false;
pendingCallInEcm = false;
}
phone.unsetOnEcbModeExitResponse(this);
break;
@@ -971,6 +991,19 @@ public final class CdmaCallTracker extends CallTracker {
}
}
/**
* Handle Ecm timer to be canceled or re-started
*/
private void handleEcmTimer(int action) {
phone.handleTimerInEmergencyCallbackMode(action);
switch(action) {
case CDMAPhone.CANCEL_ECM_TIMER: mIsEcmTimerCanceled = true; break;
case CDMAPhone.RESTART_ECM_TIMER: mIsEcmTimerCanceled = false; break;
default:
Log.e(LOG_TAG, "handleEcmTimer, unsupported action " + action);
}
}
protected void log(String msg) {
Log.d(LOG_TAG, "[CdmaCallTracker] " + msg);
}