From 89bd269975cae2d44c871c997b4eb0d42ba1f43c Mon Sep 17 00:00:00 2001 From: Robert Greenwalt Date: Fri, 11 Sep 2009 11:27:04 -0700 Subject: Handle secondary APN connect failures. Without this we'd only try a secondary APN once and the stop silently, leaving no APN connected. Adds a second retry manager with configuration strings to do a more approriate retry. Don't retry secondary apn forever. On permanent failure or retry count hit, we send a Phone.REASON_APN_FAILED disconnect status. bug: 2112114 --- .../internal/telephony/DataConnectionTracker.java | 101 ++++++++++++++------- .../java/com/android/internal/telephony/Phone.java | 1 + .../telephony/gsm/GsmDataConnectionTracker.java | 45 +++++++-- 3 files changed, 106 insertions(+), 41 deletions(-) (limited to 'telephony') diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java index ece708a..8d2785a 100644 --- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java @@ -100,7 +100,6 @@ public abstract class DataConnectionTracker extends Handler { public static final int EVENT_CLEAN_UP_CONNECTION = 34; protected static final int EVENT_CDMA_OTA_PROVISION = 35; protected static final int EVENT_RESTART_RADIO = 36; - private static final int EVENT_ENABLE_APN_REQUEST = 37; /***** Constants *****/ @@ -126,6 +125,10 @@ public abstract class DataConnectionTracker extends Handler { + "5000,10000,20000,40000,80000:5000,160000:5000," + "320000:5000,640000:5000,1280000:5000,1800000:5000"; + /** Retry configuration for secondary networks: 4 tries in 20 sec */ + protected static final String SECONDARY_DATA_RETRY_CONFIG = + "max_retries=3; 5000, 5000, 5000"; + /** Slow poll when attempting connection recovery. */ protected static final int POLL_NETSTAT_SLOW_MILLIS = 5000; /** Default ping deadline, in seconds. */ @@ -171,7 +174,7 @@ public abstract class DataConnectionTracker extends Handler { protected boolean netStatPollEnabled = false; /** Manage the behavior of data retry after failure */ - protected final RetryManager mRetryMgr = new RetryManager(); + protected RetryManager mRetryMgr = new RetryManager(); // wifi connection status will be updated by sticky intent protected boolean mIsWifiConnected = false; @@ -266,33 +269,8 @@ public abstract class DataConnectionTracker extends Handler { public void handleMessage (Message msg) { switch (msg.what) { - case EVENT_ENABLE_APN_REQUEST: - int apnId = msg.arg1; - synchronized (this) { - if (DBG) { - Log.d(LOG_TAG, "got EVENT_ENABLE_APN_REQUEST with apnType = " + apnId + - " and enable = " + msg.arg2); - Log.d(LOG_TAG, "dataEnabled[apnId] = " + dataEnabled[apnId] + - ", enabledCount = " + enabledCount); - } - if (msg.arg2 == APN_ENABLED) { - // enable - if (!dataEnabled[apnId]) { - dataEnabled[apnId] = true; - enabledCount++; - } - onTrySetupData(null); - } else { - // disable - if (dataEnabled[apnId]) { - dataEnabled[apnId] = false; - enabledCount--; - if (enabledCount == 0) { - onCleanUpConnection(true, Phone.REASON_DATA_DISABLED); - } - } - } - } + case EVENT_ENABLE_NEW_APN: + onEnableApn(msg.arg1, msg.arg2); break; case EVENT_TRY_SETUP_DATA: @@ -392,6 +370,24 @@ public abstract class DataConnectionTracker extends Handler { } } + protected String apnIdToType(int id) { + switch (id) { + case APN_DEFAULT_ID: + return Phone.APN_TYPE_DEFAULT; + case APN_MMS_ID: + return Phone.APN_TYPE_MMS; + case APN_SUPL_ID: + return Phone.APN_TYPE_SUPL; + case APN_DUN_ID: + return Phone.APN_TYPE_DUN; + case APN_HIPRI_ID: + return Phone.APN_TYPE_HIPRI; + default: + Log.e(LOG_TAG, "Unknown id (" + id + ") in apnIdToType"); + return Phone.APN_TYPE_DEFAULT; + } + } + protected abstract boolean isApnTypeActive(String type); protected abstract boolean isApnTypeAvailable(String type); @@ -449,8 +445,6 @@ public abstract class DataConnectionTracker extends Handler { } setEnabled(id, true); - mRequestedApnType = type; - sendMessage(obtainMessage(EVENT_ENABLE_NEW_APN)); return Phone.APN_REQUEST_STARTED; } @@ -471,7 +465,6 @@ public abstract class DataConnectionTracker extends Handler { if (isEnabled(id)) { setEnabled(id, false); if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) { - mRequestedApnType = Phone.APN_TYPE_DEFAULT; if (dataEnabled[APN_DEFAULT_ID]) { return Phone.APN_ALREADY_ACTIVE; } else { @@ -485,16 +478,56 @@ public abstract class DataConnectionTracker extends Handler { } } - protected void setEnabled(int id, boolean enable) { + private void setEnabled(int id, boolean enable) { if (DBG) Log.d(LOG_TAG, "setEnabled(" + id + ", " + enable + ") with old state = " + dataEnabled[id] + " and enabledCount = " + enabledCount); - Message msg = obtainMessage(EVENT_ENABLE_APN_REQUEST); + Message msg = obtainMessage(EVENT_ENABLE_NEW_APN); msg.arg1 = id; msg.arg2 = (enable ? APN_ENABLED : APN_DISABLED); sendMessage(msg); } + protected synchronized void onEnableApn(int apnId, int enabled) { + if (DBG) { + Log.d(LOG_TAG, "got EVENT_APN_ENABLE_REQUEST with apnType = " + apnId + + " and enable = " + enabled); + Log.d(LOG_TAG, "dataEnabled[apnId] = " + dataEnabled[apnId] + + ", enabledCount = " + enabledCount); + } + if (enabled == APN_ENABLED) { + if (!dataEnabled[apnId]) { + mRequestedApnType = apnIdToType(apnId); + onEnableNewApn(); + + dataEnabled[apnId] = true; + enabledCount++; + } + onTrySetupData(null); + } else { + // disable + if (dataEnabled[apnId]) { + dataEnabled[apnId] = false; + enabledCount--; + if (enabledCount == 0) { + onCleanUpConnection(true, Phone.REASON_DATA_DISABLED); + } else if (dataEnabled[APN_DEFAULT_ID] == true) { + mRequestedApnType = Phone.APN_TYPE_DEFAULT; + onEnableNewApn(); + } + } + } + } + + /** + * Called when we switch APNs. + * + * mRequestedApnType is set prior to call + * To be overridden. + */ + protected void onEnableNewApn() { + } + /** * Prevent mobile data connections from being established, * or once again allow mobile data connections. If the state diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java index 5203d3f..f32837f 100644 --- a/telephony/java/com/android/internal/telephony/Phone.java +++ b/telephony/java/com/android/internal/telephony/Phone.java @@ -154,6 +154,7 @@ public interface Phone { static final String REASON_CDMA_DATA_DETACHED = "cdmaDataDetached"; static final String REASON_APN_CHANGED = "apnChanged"; static final String REASON_APN_SWITCHED = "apnSwitched"; + static final String REASON_APN_FAILED = "apnFailed"; static final String REASON_RESTORE_DEFAULT_APN = "restoreDefaultApn"; static final String REASON_RADIO_TURNED_OFF = "radioTurnedOff"; static final String REASON_PDP_RESET = "pdpReset"; diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index 0215ab2..b063e0a 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -150,6 +150,11 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { static final String APN_ID = "apn_id"; private boolean canSetPreferApn = false; + // for tracking retrys on the default APN + private RetryManager mDefaultRetryManager; + // for tracking retrys on a secondary APN + private RetryManager mSecondaryRetryManager; + BroadcastReceiver mIntentReceiver = new BroadcastReceiver () { @Override @@ -253,6 +258,19 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { mRetryMgr.configure(20, 2000, 1000); } } + + mDefaultRetryManager = mRetryMgr; + mSecondaryRetryManager = new RetryManager(); + + if (!mSecondaryRetryManager.configure(SystemProperties.get( + "ro.gsm.2nd_data_retry_config"))) { + if (!mSecondaryRetryManager.configure(SECONDARY_DATA_RETRY_CONFIG)) { + // Should never happen, log an error and default to a simple sequence. + Log.e(LOG_TAG, "Could note configure using SECONDARY_DATA_RETRY_CONFIG=" + + SECONDARY_DATA_RETRY_CONFIG); + mSecondaryRetryManager.configure("max_retries=3, 333, 333, 333"); + } + } } public void dispose() { @@ -1019,6 +1037,12 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) { if (state == State.FAILED) { if (!mRetryMgr.isRetryNeeded()) { + if (!mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) { + // if no more retries on a secondary APN attempt, tell the world and revert. + phone.notifyDataConnection(Phone.REASON_APN_FAILED); + onEnableApn(apnTypeToId(mRequestedApnType), APN_DISABLED); + return; + } if (mReregisterOnReconnectFailure) { // We've re-registerd once now just retry forever. mRetryMgr.retryForeverUsingLastTimeout(); @@ -1069,7 +1093,16 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, Phone.REASON_SIM_LOADED)); } + @Override protected void onEnableNewApn() { + // change our retry manager to use the appropriate numbers for the new APN + if (mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) { + mRetryMgr = mDefaultRetryManager; + } else { + mRetryMgr = mSecondaryRetryManager; + } + mRetryMgr.resetRetryCount(); + // TODO: To support simultaneous PDP contexts, this should really only call // cleanUpConnection if it needs to free up a PdpConnection. cleanUpConnection(true, Phone.REASON_APN_SWITCHED); @@ -1189,6 +1222,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { // No try for permanent failure if (cause.isPermanentFail()) { notifyNoData(cause); + if (!mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) { + phone.notifyDataConnection(Phone.REASON_APN_FAILED); + onEnableApn(apnTypeToId(mRequestedApnType), APN_DISABLED); + } return; } @@ -1381,9 +1418,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { private void startDelayedRetry(PdpConnection.FailCause cause, String reason) { notifyNoData(cause); - if (mRequestedApnType == Phone.APN_TYPE_DEFAULT) { - reconnectAfterFail(cause, reason); - } + reconnectAfterFail(cause, reason); } private void setPreferredApn(int pos) { @@ -1442,10 +1477,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { onRecordsLoaded(); break; - case EVENT_ENABLE_NEW_APN: - onEnableNewApn(); - break; - case EVENT_GPRS_DETACHED: onGprsDetached(); break; -- cgit v1.1