Airplane mode on always timed out when camping on LTE
While on LTE, GsmDataConnectionTracker is implicitly associated with CdmaServiceTracker. CdmaServiceTracker asynchronously waits for the disconnection of data before turning off the Radio but GsmDataConnection does not notify the disconnection due to different logic in GsmServiceTracker. This fix is to have common airplane mode toggle logic on both GSM and CDMA flavors. Change-Id: I67ff82a59a2243856ae3e7c5e37b5726bcbf3c94
This commit is contained in:
@@ -68,6 +68,9 @@ public abstract class ServiceStateTracker extends Handler {
|
||||
protected RegistrantList mPsRestrictEnabledRegistrants = new RegistrantList();
|
||||
protected RegistrantList mPsRestrictDisabledRegistrants = new RegistrantList();
|
||||
|
||||
/* Radio power off pending flag and tag counter */
|
||||
private boolean mPendingRadioPowerOffAfterDataOff = false;
|
||||
private int mPendingRadioPowerOffAfterDataOffTag = 0;
|
||||
|
||||
protected static final boolean DBG = true;
|
||||
|
||||
@@ -77,8 +80,6 @@ public abstract class ServiceStateTracker extends Handler {
|
||||
/** Waiting period before recheck gprs and voice registration. */
|
||||
public static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000;
|
||||
|
||||
public static final int DATA_STATE_POLL_SLEEP_MS = 100;
|
||||
|
||||
/** GSM events */
|
||||
protected static final int EVENT_RADIO_STATE_CHANGED = 1;
|
||||
protected static final int EVENT_NETWORK_STATE_CHANGED = 2;
|
||||
@@ -262,7 +263,29 @@ public abstract class ServiceStateTracker extends Handler {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void handleMessage(Message msg);
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case EVENT_SET_RADIO_POWER_OFF:
|
||||
synchronized(this) {
|
||||
if (mPendingRadioPowerOffAfterDataOff &&
|
||||
(msg.arg1 == mPendingRadioPowerOffAfterDataOffTag)) {
|
||||
if (DBG) log("EVENT_SET_RADIO_OFF, turn radio off now.");
|
||||
hangupAndPowerOff();
|
||||
mPendingRadioPowerOffAfterDataOffTag += 1;
|
||||
mPendingRadioPowerOffAfterDataOff = false;
|
||||
} else {
|
||||
log("EVENT_SET_RADIO_OFF is stale arg1=" + msg.arg1 +
|
||||
"!= tag=" + mPendingRadioPowerOffAfterDataOffTag);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
log("Unhandled message with number: " + msg.what);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Phone getPhone();
|
||||
protected abstract void handlePollStateResult(int what, AsyncResult ar);
|
||||
@@ -370,7 +393,52 @@ public abstract class ServiceStateTracker extends Handler {
|
||||
*
|
||||
* Hang up the existing voice calls to decrease call drop rate.
|
||||
*/
|
||||
public abstract void powerOffRadioSafely();
|
||||
public void powerOffRadioSafely(DataConnectionTracker dcTracker) {
|
||||
synchronized (this) {
|
||||
if (!mPendingRadioPowerOffAfterDataOff) {
|
||||
if (dcTracker.isAnyActiveDataConnections()) {
|
||||
dcTracker.cleanUpAllConnections(null);
|
||||
Message msg = Message.obtain(this);
|
||||
msg.what = EVENT_SET_RADIO_POWER_OFF;
|
||||
msg.arg1 = ++mPendingRadioPowerOffAfterDataOffTag;
|
||||
if (sendMessageDelayed(msg, 30000)) {
|
||||
if (DBG) log("Wait upto 30s for data to disconnect, then turn off radio.");
|
||||
mPendingRadioPowerOffAfterDataOff = true;
|
||||
} else {
|
||||
log("Cannot send delayed Msg, turn off radio right away.");
|
||||
hangupAndPowerOff();
|
||||
}
|
||||
} else {
|
||||
dcTracker.cleanUpAllConnections(null);
|
||||
if (DBG) log("Data disconnected, turn off radio right away.");
|
||||
hangupAndPowerOff();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* process the pending request to turn radio off after data is disconnected
|
||||
*
|
||||
* return true if there is pending request to process; false otherwise.
|
||||
*/
|
||||
public boolean processPendingRadioPowerOffAfterDataOff() {
|
||||
synchronized(this) {
|
||||
if (mPendingRadioPowerOffAfterDataOff) {
|
||||
if (DBG) log("Process pending request to turn radio off.");
|
||||
mPendingRadioPowerOffAfterDataOffTag += 1;
|
||||
hangupAndPowerOff();
|
||||
mPendingRadioPowerOffAfterDataOff = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hang up all voice call and turn off radio. Implemented by derived class.
|
||||
*/
|
||||
protected abstract void hangupAndPowerOff();
|
||||
|
||||
/** Cancel a pending (if any) pollState() operation */
|
||||
protected void cancelPollState() {
|
||||
|
||||
@@ -906,6 +906,11 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnyActiveDataConnections() {
|
||||
return (mState != State.IDLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void log(String s) {
|
||||
Log.d(LOG_TAG, "[CdmaDataConnectionTracker] " + s);
|
||||
|
||||
@@ -139,8 +139,6 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
|
||||
private boolean isEriTextLoaded = false;
|
||||
private boolean isSubscriptionFromRuim = false;
|
||||
|
||||
private boolean mPendingRadioPowerOffAfterDataOff = false;
|
||||
|
||||
/* Used only for debugging purposes. */
|
||||
private String mRegistrationDeniedReason;
|
||||
|
||||
@@ -485,18 +483,8 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
|
||||
}
|
||||
break;
|
||||
|
||||
case EVENT_SET_RADIO_POWER_OFF:
|
||||
synchronized(this) {
|
||||
if (mPendingRadioPowerOffAfterDataOff) {
|
||||
if (DBG) log("EVENT_SET_RADIO_OFF, turn radio off now.");
|
||||
hangupAndPowerOff();
|
||||
mPendingRadioPowerOffAfterDataOff = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Log.e(LOG_TAG, "Unhandled message with number: " + msg.what);
|
||||
super.handleMessage(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -513,35 +501,10 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
|
||||
DataConnectionTracker dcTracker = phone.mDataConnection;
|
||||
|
||||
// If it's on and available and we want it off gracefully
|
||||
powerOffRadioSafely();
|
||||
powerOffRadioSafely(dcTracker);
|
||||
} // Otherwise, we're in the desired state
|
||||
}
|
||||
|
||||
// TODO: Consider moving this method to DataConnectionTracker
|
||||
@Override
|
||||
public void powerOffRadioSafely() {
|
||||
DataConnectionTracker dcTracker = phone.mDataConnection;
|
||||
|
||||
synchronized (this) {
|
||||
if (!mPendingRadioPowerOffAfterDataOff) {
|
||||
if (dcTracker.isAnyActiveDataConnections()) {
|
||||
dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
|
||||
if (sendEmptyMessageDelayed(EVENT_SET_RADIO_POWER_OFF, 30000)) {
|
||||
if (DBG) log("Wait upto 30s 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();
|
||||
}
|
||||
} else {
|
||||
dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
|
||||
if (DBG) log("Data disconnected, turn off radio right away.");
|
||||
hangupAndPowerOff();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateSpnDisplay() {
|
||||
// TODO RUIM SPN is not implemented, EF_SPN has to be read and Display Condition
|
||||
@@ -1657,24 +1620,6 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
|
||||
return mIsMinInfoReady;
|
||||
}
|
||||
|
||||
/**
|
||||
* process the pending request to turn radio off after data is disconnected
|
||||
*
|
||||
* return true if there is pending request to process; false otherwise.
|
||||
*/
|
||||
public boolean processPendingRadioPowerOffAfterDataOff() {
|
||||
synchronized(this) {
|
||||
if (mPendingRadioPowerOffAfterDataOff) {
|
||||
if (DBG) log("Process pending request to turn radio off.");
|
||||
removeMessages(EVENT_SET_RADIO_POWER_OFF);
|
||||
hangupAndPowerOff();
|
||||
mPendingRadioPowerOffAfterDataOff = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns OTASP_UNKNOWN, OTASP_NEEDED or OTASP_NOT_NEEDED
|
||||
*/
|
||||
@@ -1701,7 +1646,8 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
|
||||
Log.d(LOG_TAG, "[CdmaServiceStateTracker] " + s);
|
||||
}
|
||||
|
||||
private void hangupAndPowerOff() {
|
||||
@Override
|
||||
protected void hangupAndPowerOff() {
|
||||
// hang up all active voice calls
|
||||
phone.mCT.ringingCall.hangupIfAlive();
|
||||
phone.mCT.backgroundCall.hangupIfAlive();
|
||||
|
||||
@@ -1073,7 +1073,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
|
||||
protected void restartRadio() {
|
||||
log("************TURN OFF RADIO**************");
|
||||
cleanUpAllConnections(true, Phone.REASON_RADIO_TURNED_OFF);
|
||||
mPhone.getServiceStateTracker().powerOffRadioSafely();
|
||||
mPhone.getServiceStateTracker().powerOffRadioSafely(this);
|
||||
/* 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
|
||||
@@ -1491,14 +1491,25 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
|
||||
}
|
||||
|
||||
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
|
||||
|
||||
apnContext.setState(State.IDLE);
|
||||
apnContext.setApnSetting(null);
|
||||
|
||||
// if all data connection are gone, check whether Airplane mode request was
|
||||
// pending.
|
||||
if (!isConnected()) {
|
||||
if (mPhone.getServiceStateTracker().processPendingRadioPowerOffAfterDataOff()) {
|
||||
// Radio will be turned off. No need to retry data setup
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if APN disabled.
|
||||
if (apnContext.getPendingAction() == ApnContext.PENDING_ACTION_APN_DISABLE) {
|
||||
mApnContexts.remove(apnContext.getApnType());
|
||||
return;
|
||||
}
|
||||
|
||||
apnContext.setState(State.IDLE);
|
||||
apnContext.setApnSetting(null);
|
||||
if (TextUtils.equals(apnContext.getApnType(), Phone.APN_TYPE_DEFAULT)
|
||||
&& retryAfterDisconnected(apnContext.getReason())) {
|
||||
SystemProperties.set("gsm.defaultpdpcontext.active", "false");
|
||||
@@ -1893,6 +1904,11 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnyActiveDataConnections() {
|
||||
return isConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void log(String s) {
|
||||
Log.d(LOG_TAG, "[GsmDataConnectionTracker] " + s);
|
||||
|
||||
@@ -164,8 +164,6 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
|
||||
static final int PS_NOTIFICATION = 888; // Id to update and cancel PS restricted
|
||||
static final int CS_NOTIFICATION = 999; // Id to update and cancel CS restricted
|
||||
|
||||
static final int MAX_NUM_DATA_STATE_READS = 15;
|
||||
|
||||
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
@@ -459,7 +457,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
|
||||
break;
|
||||
|
||||
default:
|
||||
Log.e(LOG_TAG, "Unhandled message with number: " + msg.what);
|
||||
super.handleMessage(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -471,23 +469,13 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
|
||||
cm.setRadioPower(true, null);
|
||||
} else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
|
||||
// If it's on and available and we want it off gracefully
|
||||
powerOffRadioSafely();
|
||||
DataConnectionTracker dcTracker = phone.mDataConnection;
|
||||
powerOffRadioSafely(dcTracker);
|
||||
} // Otherwise, we're in the desired state
|
||||
}
|
||||
|
||||
@Override
|
||||
public void powerOffRadioSafely() {
|
||||
// Cleanup all connections
|
||||
DataConnectionTracker dcTracker = phone.mDataConnection;
|
||||
Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_ALL_CONNECTIONS);
|
||||
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++) {
|
||||
SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS);
|
||||
}
|
||||
|
||||
protected void hangupAndPowerOff() {
|
||||
// hang up all active voice calls
|
||||
if (phone.isInCall()) {
|
||||
phone.mCT.ringingCall.hangupIfAlive();
|
||||
|
||||
Reference in New Issue
Block a user