diff options
author | John Wang <johnwang@google.com> | 2010-01-06 15:29:02 -0800 |
---|---|---|
committer | John Wang <johnwang@google.com> | 2010-01-11 15:48:47 -0800 |
commit | 3805c7ca324f232972c959e06253de4242f83607 (patch) | |
tree | c4f4298edc0286c3324cb2eb9ab8ded0444c17a1 /telephony/java | |
parent | 6d40ee33f534aa31c5d9c4dbc6049275e3b754c2 (diff) | |
download | frameworks_base-3805c7ca324f232972c959e06253de4242f83607.zip frameworks_base-3805c7ca324f232972c959e06253de4242f83607.tar.gz frameworks_base-3805c7ca324f232972c959e06253de4242f83607.tar.bz2 |
Hangup calls before powering off radio.
Bug 2339655. Should hangup the existing voice call (including onhold ones) before powering off radio to ensure the proper sequence at radio protocol level. Otherwise the carrier will treat it as drop calls.
Diffstat (limited to 'telephony/java')
5 files changed, 99 insertions, 42 deletions
diff --git a/telephony/java/com/android/internal/telephony/Call.java b/telephony/java/com/android/internal/telephony/Call.java index b95dd11..4967ab8 100644 --- a/telephony/java/com/android/internal/telephony/Call.java +++ b/telephony/java/com/android/internal/telephony/Call.java @@ -18,6 +18,8 @@ package com.android.internal.telephony; import java.util.List; +import android.util.Log; + /** * {@hide} */ @@ -54,6 +56,8 @@ public abstract class Call { // merged, etc. protected boolean isGeneric = false; + protected final String LOG_TAG = "Call"; + /* Instance Methods */ /** Do not modify the List result!!! This list is not yours to keep @@ -235,4 +239,17 @@ public abstract class Call { public void setGeneric(boolean generic) { isGeneric = generic; } + + /** + * Hangup call if it is alive + */ + public void hangupIfAlive() { + if (getState().isAlive()) { + try { + hangup(); + } catch (CallStateException ex) { + Log.w(LOG_TAG, " hangupIfActive: caught " + ex); + } + } + } } diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java index 6892998..7383649 100644 --- a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java @@ -271,6 +271,13 @@ public abstract class ServiceStateTracker extends Handler { protected abstract void updateSpnDisplay(); protected abstract void setPowerStateToDesired(); + /** + * Clean up existing voice and data connection then turn off radio power. + * + * Hang up the existing voice calls to decrease call drop rate. + */ + protected abstract void powerOffRadioSafely(); + /** Cancel a pending (if any) pollState() operation */ protected void cancelPollState() { // This will effectively cancel the rest of the poll requests. diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java index af3cbd5..42feaa9 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java @@ -514,7 +514,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { synchronized(this) { if (mPendingRadioPowerOffAfterDataOff) { if (DBG) log("EVENT_SET_RADIO_OFF, turn radio off now."); - cm.setRadioPower(false, null); + hangupAndPowerOff(); mPendingRadioPowerOffAfterDataOff = false; } } @@ -541,32 +541,42 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { dcTracker.getStateInString(), dcTracker.getAnyDataEnabled() ? 1 : 0); } - Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION); - msg.arg1 = 1; // tearDown is true - msg.obj = CDMAPhone.REASON_RADIO_TURNED_OFF; - dcTracker.sendMessage(msg); - synchronized(this) { - if (!mPendingRadioPowerOffAfterDataOff) { - DataConnectionTracker.State currentState = dcTracker.getState(); - if (currentState != DataConnectionTracker.State.CONNECTED - && currentState != DataConnectionTracker.State.DISCONNECTING - && currentState != DataConnectionTracker.State.INITING) { - if (DBG) log("Data disconnected, turn off radio right away."); - cm.setRadioPower(false, null); - } - else if (sendEmptyMessageDelayed(EVENT_SET_RADIO_POWER_OFF, 30000)) { - if (DBG) { - log("Wait up to 30 sec for data to disconnect, then turn off radio."); - } - mPendingRadioPowerOffAfterDataOff = true; - } else { - Log.w(LOG_TAG, "Cannot send delayed Msg, turn off radio right away."); - cm.setRadioPower(false, null); + // If it's on and available and we want it off gracefully + powerOffRadioSafely(); + } // Otherwise, we're in the desired state + } + + @Override + protected void powerOffRadioSafely(){ + // clean data connection + DataConnectionTracker dcTracker = phone.mDataConnection; + + Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION); + msg.arg1 = 1; // tearDown is true + msg.obj = CDMAPhone.REASON_RADIO_TURNED_OFF; + dcTracker.sendMessage(msg); + + synchronized(this) { + if (!mPendingRadioPowerOffAfterDataOff) { + DataConnectionTracker.State currentState = dcTracker.getState(); + if (currentState != DataConnectionTracker.State.CONNECTED + && currentState != DataConnectionTracker.State.DISCONNECTING + && currentState != DataConnectionTracker.State.INITING) { + if (DBG) log("Data disconnected, turn off radio right away."); + hangupAndPowerOff(); + } + else if (sendEmptyMessageDelayed(EVENT_SET_RADIO_POWER_OFF, 30000)) { + if (DBG) { + log("Wait up to 30 sec for data to disconnect, then turn off radio."); } + mPendingRadioPowerOffAfterDataOff = true; + } else { + Log.w(LOG_TAG, "Cannot send delayed Msg, turn off radio right away."); + hangupAndPowerOff(); } } - } // Otherwise, we're in the desired state + } } @Override @@ -1644,11 +1654,19 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { if (mPendingRadioPowerOffAfterDataOff) { if (DBG) log("Process pending request to turn radio off."); removeMessages(EVENT_SET_RADIO_POWER_OFF); - cm.setRadioPower(false, null); + hangupAndPowerOff(); mPendingRadioPowerOffAfterDataOff = false; return true; } return false; } } + + private void hangupAndPowerOff() { + // hang up all active voice calls + phone.mCT.ringingCall.hangupIfAlive(); + phone.mCT.backgroundCall.hangupIfAlive(); + phone.mCT.foregroundCall.hangupIfAlive(); + cm.setRadioPower(false, null); + } } diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index 3f52eff..6695ccb 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -808,7 +808,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { protected void restartRadio() { Log.d(LOG_TAG, "************TURN OFF RADIO**************"); cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF); - phone.mCM.setRadioPower(false, null); + mGsmPhone.mSST.powerOffRadioSafely(); /* Note: no need to call setRadioPower(true). Assuming the desired * radio power state is still ON (as tracked by ServiceStateTracker), * ServiceStateTracker will call setRadioPower when it receives the diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java index c2c89c01..48e5c97 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java @@ -518,26 +518,41 @@ final class GsmServiceStateTracker extends ServiceStateTracker { EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF, dcTracker.getStateInString(), dcTracker.getAnyDataEnabled() ? 1 : 0); } - Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION); - msg.arg1 = 1; // tearDown is true - msg.obj = GSMPhone.REASON_RADIO_TURNED_OFF; - dcTracker.sendMessage(msg); - - // poll data state up to 15 times, with a 100ms delay - // totaling 1.5 sec. Normal data disable action will finish in 100ms. - for (int i = 0; i < MAX_NUM_DATA_STATE_READS; i++) { - if (dcTracker.getState() != DataConnectionTracker.State.CONNECTED - && dcTracker.getState() != DataConnectionTracker.State.DISCONNECTING) { - Log.d(LOG_TAG, "Data shutdown complete."); - break; - } - SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS); - } - // If it's on and available and we want it off.. - cm.setRadioPower(false, null); + // If it's on and available and we want it off gracefully + powerOffRadioSafely(); } // Otherwise, we're in the desired state } + @Override + protected void powerOffRadioSafely() { + // clean data connection + DataConnectionTracker dcTracker = phone.mDataConnection; + Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION); + msg.arg1 = 1; // tearDown is true + msg.obj = GSMPhone.REASON_RADIO_TURNED_OFF; + dcTracker.sendMessage(msg); + + // poll data state up to 15 times, with a 100ms delay + // totaling 1.5 sec. Normal data disable action will finish in 100ms. + for (int i = 0; i < MAX_NUM_DATA_STATE_READS; i++) { + if (dcTracker.getState() != DataConnectionTracker.State.CONNECTED + && dcTracker.getState() != DataConnectionTracker.State.DISCONNECTING) { + Log.d(LOG_TAG, "Data shutdown complete."); + break; + } + SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS); + } + + // hang up all active voice calls + if (phone.isInCall()) { + phone.mCT.ringingCall.hangupIfAlive(); + phone.mCT.backgroundCall.hangupIfAlive(); + phone.mCT.foregroundCall.hangupIfAlive(); + } + + cm.setRadioPower(false, null); + } + protected void updateSpnDisplay() { int rule = phone.mSIMRecords.getDisplayRule(ss.getOperatorNumeric()); String spn = phone.mSIMRecords.getServiceProviderName(); |