summaryrefslogtreecommitdiffstats
path: root/telephony/java
diff options
context:
space:
mode:
authorJohn Wang <johnwang@google.com>2010-01-06 15:29:02 -0800
committerJohn Wang <johnwang@google.com>2010-01-11 15:48:47 -0800
commit3805c7ca324f232972c959e06253de4242f83607 (patch)
treec4f4298edc0286c3324cb2eb9ab8ded0444c17a1 /telephony/java
parent6d40ee33f534aa31c5d9c4dbc6049275e3b754c2 (diff)
downloadframeworks_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')
-rw-r--r--telephony/java/com/android/internal/telephony/Call.java17
-rw-r--r--telephony/java/com/android/internal/telephony/ServiceStateTracker.java7
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java66
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java2
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java49
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();