Merge change 24754 into eclair

* changes:
  Handle secondary APN connect failures.
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 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 @@
         + "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 @@
     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 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 @@
         }
     }
 
+    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 @@
         }
 
         setEnabled(id, true);
-        mRequestedApnType = type;
-        sendMessage(obtainMessage(EVENT_ENABLE_NEW_APN));
         return Phone.APN_REQUEST_STARTED;
     }
 
@@ -471,7 +465,6 @@
         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 @@
         }
     }
 
-    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 @@
     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 @@
     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 @@
                 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 @@
     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 @@
         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 @@
             // 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 @@
 
     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 @@
                 onRecordsLoaded();
                 break;
 
-            case EVENT_ENABLE_NEW_APN:
-                onEnableNewApn();
-                break;
-
             case EVENT_GPRS_DETACHED:
                 onGprsDetached();
                 break;