Merge "Fixed problem with setting updated values on existing animators"
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index 7743ceb..cd08e33 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -39,8 +39,6 @@
 
     // NfcAdapter-class related methods
     boolean isEnabled();
-    NdefMessage localGet();
-    void localSet(in NdefMessage message);
     void openTagConnection(in Tag tag);
 
     // Non-public methods
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index cf80faf..88b6ea4 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -301,48 +301,6 @@
     }
 
     /**
-     * Set the NDEF Message that this NFC adapter should appear as to Tag
-     * readers.
-     * <p>
-     * Any Tag reader can read the contents of the local tag when it is in
-     * proximity, without any further user confirmation.
-     * <p>
-     * The implementation of this method must either
-     * <ul>
-     * <li>act as a passive tag containing this NDEF message
-     * <li>provide the NDEF message on over LLCP to peer NFC adapters
-     * </ul>
-     * The NDEF message is preserved across reboot.
-     * <p>Requires {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param message NDEF message to make public
-     * @hide
-     */
-    public void setLocalNdefMessage(NdefMessage message) {
-        try {
-            mService.localSet(message);
-        } catch (RemoteException e) {
-            attemptDeadServiceRecovery(e);
-        }
-    }
-
-    /**
-     * Get the NDEF Message that this adapter appears as to Tag readers.
-     * <p>Requires {@link android.Manifest.permission#NFC} permission.
-     *
-     * @return NDEF Message that is publicly readable
-     * @hide
-     */
-    public NdefMessage getLocalNdefMessage() {
-        try {
-            return mService.localGet();
-        } catch (RemoteException e) {
-            attemptDeadServiceRecovery(e);
-            return null;
-        }
-    }
-
-    /**
      * Create a raw tag connection to the default Target
      * <p>Requires {@link android.Manifest.permission#NFC} permission.
      * @hide
diff --git a/core/java/com/android/internal/widget/WaveView.java b/core/java/com/android/internal/widget/WaveView.java
index f4ee7ee..f91d3d6 100644
--- a/core/java/com/android/internal/widget/WaveView.java
+++ b/core/java/com/android/internal/widget/WaveView.java
@@ -53,8 +53,10 @@
     private static final int STATE_UNLOCK_SUCCESS = 5;
 
     // Animation properties.
-    private static final long DURATION = 500; // duration of transitional animations
-    private static final long FINAL_DELAY = 1300; // delay for final animations
+    private static final long DURATION = 300; // duration of transitional animations
+    private static final long FINAL_DURATION = 200; // duration of final animations when unlocking
+    private static final long RING_DELAY = 1300; // when to start fading animated rings
+    private static final long FINAL_DELAY = 200; // delay for unlock success animation
     private static final long SHORT_DELAY = 100; // for starting one animation after another.
     private static final long WAVE_DURATION = 2000; // amount of time for way to expand/decay
     private static final long RESET_TIMEOUT = 3000; // elapsed time of inactivity before we reset
@@ -299,11 +301,11 @@
                         // x:ringX, y:ringY, scaleX: .1, scaleY: .1, ease:Quint.easeOut});
                         DrawableHolder wave = mLightWaves.get(n);
                         long delay = 1000L*(6 + n - mCurrentWave)/10L;
-                        wave.addAnimTo(DURATION, delay, "x", ringX, true);
-                        wave.addAnimTo(DURATION, delay, "y", ringY, true);
-                        wave.addAnimTo(DURATION, delay, "scaleX", 0.1f, true);
-                        wave.addAnimTo(DURATION, delay, "scaleY", 0.1f, true);
-                        wave.addAnimTo(DURATION, delay, "alpha", 0.0f, true);
+                        wave.addAnimTo(FINAL_DURATION, delay, "x", ringX, true);
+                        wave.addAnimTo(FINAL_DURATION, delay, "y", ringY, true);
+                        wave.addAnimTo(FINAL_DURATION, delay, "scaleX", 0.1f, true);
+                        wave.addAnimTo(FINAL_DURATION, delay, "scaleY", 0.1f, true);
+                        wave.addAnimTo(FINAL_DURATION, delay, "alpha", 0.0f, true);
                     }
                     for (int i = 0; i < mLightWaves.size(); i++) {
                         mLightWaves.get(i).startAnimations(this);
@@ -311,14 +313,14 @@
 
                     //TweenMax.to(unlockRing, .5, {x:ringX, y: ringY, scaleX: .1, scaleY: .1,
                     // alpha: 0, ease: Quint.easeOut   });
-                    mUnlockRing.addAnimTo(DURATION, 0, "x", ringX, false);
-                    mUnlockRing.addAnimTo(DURATION, 0, "y", ringY, false);
-                    mUnlockRing.addAnimTo(DURATION, 0, "scaleX", 0.1f, false);
-                    mUnlockRing.addAnimTo(DURATION, 0, "scaleY", 0.1f, false);
-                    mUnlockRing.addAnimTo(DURATION, 0, "alpha", 0.0f, false);
+                    mUnlockRing.addAnimTo(FINAL_DURATION, 0, "x", ringX, false);
+                    mUnlockRing.addAnimTo(FINAL_DURATION, 0, "y", ringY, false);
+                    mUnlockRing.addAnimTo(FINAL_DURATION, 0, "scaleX", 0.1f, false);
+                    mUnlockRing.addAnimTo(FINAL_DURATION, 0, "scaleY", 0.1f, false);
+                    mUnlockRing.addAnimTo(FINAL_DURATION, 0, "alpha", 0.0f, false);
 
                     //TweenMax.to(unlockRing, .5, { delay: 1.3, alpha: 0  , ease: Quint.easeOut });
-                    mUnlockRing.addAnimTo(DURATION, FINAL_DELAY, "alpha", 0.0f, false);
+                    mUnlockRing.addAnimTo(FINAL_DURATION, FINAL_DELAY, "alpha", 0.0f, false);
 
                     //TweenMax.to(unlockDefault, 0, { x:ringX, y: ringY, scaleX: .1, scaleY: .1,
                     // alpha: 0  , overwrite: true });
@@ -332,27 +334,27 @@
 
                     //TweenMax.to(unlockDefault, .5, { x:ringX, y: ringY, scaleX: 1, scaleY: 1,
                     // alpha: 1  , ease: Quint.easeOut  , overwrite: true });
-                    mUnlockDefault.addAnimTo(DURATION, 0, "x", ringX, true);
-                    mUnlockDefault.addAnimTo(DURATION, 0, "y", ringY, true);
-                    mUnlockDefault.addAnimTo(DURATION, 0, "scaleX", 1.0f, true);
-                    mUnlockDefault.addAnimTo(DURATION, 0, "scaleY", 1.0f, true);
-                    mUnlockDefault.addAnimTo(DURATION, 0, "alpha", 1.0f, true);
+                    mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "x", ringX, true);
+                    mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "y", ringY, true);
+                    mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "scaleX", 1.0f, true);
+                    mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "scaleY", 1.0f, true);
+                    mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "alpha", 1.0f, true);
 
                     //TweenMax.to(unlockDefault, .5, { delay: 1.3, scaleX: 3, scaleY: 3,
                     // alpha: 1, ease: Quint.easeOut });
-                    mUnlockDefault.addAnimTo(DURATION, FINAL_DELAY, "scaleX", 3.0f, false);
-                    mUnlockDefault.addAnimTo(DURATION, FINAL_DELAY, "scaleY", 3.0f, false);
-                    mUnlockDefault.addAnimTo(DURATION, FINAL_DELAY, "alpha", 1.0f, false);
+                    mUnlockDefault.addAnimTo(FINAL_DURATION, FINAL_DELAY, "scaleX", 3.0f, false);
+                    mUnlockDefault.addAnimTo(FINAL_DURATION, FINAL_DELAY, "scaleY", 3.0f, false);
+                    mUnlockDefault.addAnimTo(FINAL_DURATION, FINAL_DELAY, "alpha", 0.0f, false);
 
                     //TweenMax.to(unlockHalo, .5, { x:ringX, y: ringY , ease: Back.easeOut    });
-                    mUnlockHalo.addAnimTo(DURATION, 0, "x", ringX, false);
-                    mUnlockHalo.addAnimTo(DURATION, 0, "y", ringY, false);
+                    mUnlockHalo.addAnimTo(FINAL_DURATION, 0, "x", ringX, false);
+                    mUnlockHalo.addAnimTo(FINAL_DURATION, 0, "y", ringY, false);
 
                     //TweenMax.to(unlockHalo, .5, { delay: 1.3, scaleX: 3, scaleY: 3,
                     // alpha: 1, ease: Quint.easeOut   });
-                    mUnlockHalo.addAnimTo(DURATION, FINAL_DELAY, "scaleX", 3.0f, false);
-                    mUnlockHalo.addAnimTo(DURATION, FINAL_DELAY, "scaleY", 3.0f, false);
-                    mUnlockHalo.addAnimTo(DURATION, FINAL_DELAY, "alpha", 1.0f, false);
+                    mUnlockHalo.addAnimTo(FINAL_DURATION, FINAL_DELAY, "scaleX", 3.0f, false);
+                    mUnlockHalo.addAnimTo(FINAL_DURATION, FINAL_DELAY, "scaleY", 3.0f, false);
+                    mUnlockHalo.addAnimTo(FINAL_DURATION, FINAL_DELAY, "alpha", 0.0f, false);
 
                     removeCallbacks(mLockTimerActions);
 
@@ -437,7 +439,7 @@
 
                 //TweenMax.to(this["lightWave"+currentWave], 1, { delay: 1.3
                 // , alpha: 0  , ease:Quint.easeOut});
-                wave.addAnimTo(1000, FINAL_DELAY, "alpha", 0.0f, false);
+                wave.addAnimTo(1000, RING_DELAY, "alpha", 0.0f, false);
                 wave.startAnimations(WaveView.this);
 
                 mCurrentWave = (mCurrentWave+1) % mWaveCount;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 855a4e0..09e01f6 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -260,25 +260,25 @@
     const GLuint previousFbo = mSnapshot->fbo;
     const int count = saveSnapshot(flags);
 
-    int alpha = 255;
-    SkXfermode::Mode mode;
+    if (!mSnapshot->invisible) {
+        int alpha = 255;
+        SkXfermode::Mode mode;
 
-    if (p) {
-        alpha = p->getAlpha();
-        if (!mCaches.extensions.hasFramebufferFetch()) {
-            const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode);
-            if (!isMode) {
-                // Assume SRC_OVER
-                mode = SkXfermode::kSrcOver_Mode;
+        if (p) {
+            alpha = p->getAlpha();
+            if (!mCaches.extensions.hasFramebufferFetch()) {
+                const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode);
+                if (!isMode) {
+                    // Assume SRC_OVER
+                    mode = SkXfermode::kSrcOver_Mode;
+                }
+            } else {
+                mode = getXfermode(p->getXfermode());
             }
         } else {
-            mode = getXfermode(p->getXfermode());
+            mode = SkXfermode::kSrcOver_Mode;
         }
-    } else {
-        mode = SkXfermode::kSrcOver_Mode;
-    }
 
-    if (!mSnapshot->previous->invisible) {
         createLayer(mSnapshot, left, top, right, bottom, alpha, mode, flags, previousFbo);
     }
 
@@ -379,8 +379,7 @@
             bounds.getHeight() > mCaches.maxTextureSize) {
         snapshot->invisible = true;
     } else {
-        snapshot->invisible = snapshot->previous->invisible ||
-                (alpha <= ALPHA_THRESHOLD && fboLayer);
+        snapshot->invisible = snapshot->invisible || (alpha <= ALPHA_THRESHOLD && fboLayer);
     }
 
     // Bail out if we won't draw in this snapshot
@@ -1011,6 +1010,9 @@
 }
 
 void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
+    // No need to check against the clip, we fill the clip region
+    if (mSnapshot->invisible) return;
+
     Rect& clip(*mSnapshot->clipRect);
     clip.snapToPixelBoundaries();
     drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true);
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 4644a7c..50d10bf 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -219,7 +219,7 @@
     }
 
     class WaveViewMethods implements WaveView.OnTriggerListener {
-        private static final int WAIT_FOR_ANIMATION_TIMEOUT = 500;
+        private static final int WAIT_FOR_ANIMATION_TIMEOUT = 0;
         private static final int STAY_ON_WHILE_GRABBED_TIMEOUT = 30000;
 
         /** {@inheritDoc} */
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index 185d413..c3ad9e6 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -261,8 +261,10 @@
     protected static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100;
 
     //***** Member Variables
+    protected int mId;
     protected int mTag;
     protected PhoneBase phone;
+    protected RetryManager mRetryMgr;
     protected int cid;
     protected LinkProperties mLinkProperties = new LinkProperties();
     protected LinkCapabilities mCapabilities = new LinkCapabilities();
@@ -285,10 +287,11 @@
 
 
    //***** Constructor
-    protected DataConnection(PhoneBase phone, String name) {
+    protected DataConnection(PhoneBase phone, String name, RetryManager rm) {
         super(name);
         if (DBG) log("DataConnection constructor E");
         this.phone = phone;
+        mRetryMgr = rm;
         this.cid = -1;
         clearSettings();
 
@@ -358,8 +361,8 @@
 
         if (dp.onCompletedMsg != null) {
             Message msg = dp.onCompletedMsg;
-            log(String.format("msg.what=%d msg.obj=%s",
-                    msg.what, ((msg.obj instanceof String) ? (String) msg.obj : "<no-reason>")));
+            log(String.format("msg=%s msg.obj=%s", msg.toString(),
+                    ((msg.obj instanceof String) ? (String) msg.obj : "<no-reason>")));
             AsyncResult.forMessage(msg);
             msg.sendToTarget();
         }
@@ -372,6 +375,10 @@
         clearSettings();
     }
 
+    public RetryManager getRetryMgr() {
+        return mRetryMgr;
+    }
+
     /**
      * Clear all settings called when entering mInactiveState.
      */
@@ -857,13 +864,13 @@
 
     /**
      * Connect to the apn and return an AsyncResult in onCompletedMsg.
-     * Used for cellular networks that use Acess Point Names (APN) such
+     * Used for cellular networks that use Acesss Point Names (APN) such
      * as GSM networks.
      *
      * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
      *        With AsyncResult.userObj set to the original msg.obj,
      *        AsyncResult.result = FailCause and AsyncResult.exception = Exception().
-     * @param apn is the Acces Point Name to connect to
+     * @param apn is the Access Point Name to connect to
      */
     public void connect(Message onCompletedMsg, ApnSetting apn) {
         sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(apn, onCompletedMsg)));
@@ -915,6 +922,13 @@
     }
 
     /**
+     * Get the DataConnection ID
+     */
+    public int getDataConnectionId() {
+        return mId;
+    }
+
+    /**
      * Return the LinkProperties for the connection.
      *
      * @return a copy of the LinkProperties, is never null.
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 52839be..f8812ec 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -16,27 +16,38 @@
 
 package com.android.internal.telephony;
 
+import com.android.internal.telephony.cdma.CDMAPhone;
+
 import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.net.IConnectivityManager;
 import android.net.LinkCapabilities;
 import android.net.LinkProperties;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiManager;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Message;
+import android.os.ServiceManager;
+import android.preference.PreferenceManager;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.text.TextUtils;
 import android.util.Log;
 
 import java.util.ArrayList;
-
+import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * {@hide}
- *
  */
 public abstract class DataConnectionTracker extends Handler {
-    protected static final boolean DBG = false;
-    protected final String LOG_TAG = "DataConnectionTracker";
+    protected static final boolean DBG = true;
 
     /**
      * IDLE: ready to start data connection setup, default state
@@ -121,9 +132,10 @@
     protected boolean mMasterDataEnabled = true;
 
     protected boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
+
     protected int enabledCount = 0;
 
-    /* Currently requested APN type */
+    /* Currently requested APN type (TODO: This should probably be a parameter not a member) */
     protected String mRequestedApnType = Phone.APN_TYPE_DEFAULT;
 
     /** Retry configuration: A doubling of retry times from 5secs to 30minutes */
@@ -165,20 +177,27 @@
     // represents an invalid IP address
     protected static final String NULL_IP = "0.0.0.0";
 
+    // TODO: See if we can remove INTENT_RECONNECT_ALARM
+    //       having to have different values for GSM and
+    //       CDMA. If so we can then remove the need for
+    //       getActionIntentReconnectAlarm.
+    protected static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason";
 
     // member variables
-    protected PhoneBase phone;
-    protected Activity activity = Activity.NONE;
-    protected State state = State.IDLE;
+    protected PhoneBase mPhone;
+    protected Activity mActivity = Activity.NONE;
+    protected State mState = State.IDLE;
     protected Handler mDataConnectionTracker = null;
 
 
-    protected long txPkts, rxPkts, sentSinceLastRecv;
-    protected int netStatPollPeriod;
+    protected long mTxPkts;
+    protected long mRxPkts;
+    protected long mSentSinceLastRecv;
+    protected int mNetStatPollPeriod;
     protected int mNoRecvPollCount = 0;
-    protected boolean netStatPollEnabled = false;
+    protected boolean mNetStatPollEnabled = false;
 
-    /** Manage the behavior of data retry after failure */
+    /** Manage the behavior of data retry after failure (TODO: One per connection in the future?) */
     protected RetryManager mRetryMgr = new RetryManager();
 
     // wifi connection status will be updated by sticky intent
@@ -188,37 +207,125 @@
     protected PendingIntent mReconnectIntent = null;
 
     /** CID of active data connection */
-    protected int cidActive;
+    protected int mCidActive;
 
     /** indication of our availability (preconditions to trysetupData are met) **/
     protected boolean mAvailability = false;
 
+    // When false we will not auto attach and manully attaching is required.
+    protected boolean mAutoAttachOnCreation = false;
+
+    // State of screen
+    // (TODO: Reconsider tying directly to screen, maybe this is
+    //        really a lower power mode")
+    protected boolean mIsScreenOn = true;
+
     /** The link properties (dns, gateway, ip, etc) */
     protected LinkProperties mLinkProperties = new LinkProperties();
 
     /** The link capabilities */
     protected LinkCapabilities mLinkCapabilities = new LinkCapabilities();
 
+    /** Allows the generation of unique Id's for DataConnection objects */
+    protected AtomicInteger mUniqueIdGenerator = new AtomicInteger(0);
+
+    /** The data connections. */
+    protected HashMap<Integer, DataConnection> mDataConnections =
+        new HashMap<Integer, DataConnection>();
+
+    protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver ()
+    {
+        @Override
+        public void onReceive(Context context, Intent intent)
+        {
+            String action = intent.getAction();
+            if (action.equals(Intent.ACTION_SCREEN_ON)) {
+                mIsScreenOn = true;
+                stopNetStatPoll();
+                startNetStatPoll();
+            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+                mIsScreenOn = false;
+                stopNetStatPoll();
+                startNetStatPoll();
+            } else if (action.equals(getActionIntentReconnectAlarm())) {
+                log("Reconnect alarm. Previous state was " + mState);
+
+                String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
+                if (mState == State.FAILED) {
+                    Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
+                    msg.arg1 = 0; // tearDown is false
+                    msg.obj = reason;
+                    sendMessage(msg);
+                }
+                sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
+            } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+                final android.net.NetworkInfo networkInfo = (NetworkInfo)
+                        intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+                mIsWifiConnected = (networkInfo != null && networkInfo.isConnected());
+            } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+                final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+                        WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
+
+                if (!enabled) {
+                    // when WiFi got disabled, the NETWORK_STATE_CHANGED_ACTION
+                    // quit and won't report disconnected until next enabling.
+                    mIsWifiConnected = false;
+                }
+            }
+        }
+    };
+
     /**
      * Default constructor
      */
     protected DataConnectionTracker(PhoneBase phone) {
         super();
-        this.phone = phone;
+        mPhone = phone;
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(getActionIntentReconnectAlarm());
+        filter.addAction(Intent.ACTION_SCREEN_ON);
+        filter.addAction(Intent.ACTION_SCREEN_OFF);
+        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+
+        // TODO: Why is this registering the phone as the receiver of the intent
+        //       and not its own handler?
+        mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
+
+        // This preference tells us 1) initial condition for "dataEnabled",
+        // and 2) whether the RIL will setup the baseband to auto-PS attach.
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
+        boolean dataEnabledSetting = true;
+        try {
+            dataEnabledSetting = IConnectivityManager.Stub.asInterface(ServiceManager.
+                    getService(Context.CONNECTIVITY_SERVICE)).getMobileDataEnabled();
+        } catch (Exception e) {
+            // nothing to do - use the old behavior and leave data on
+        }
+        dataEnabled[APN_DEFAULT_ID] =
+                !sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false) &&
+                dataEnabledSetting;
+        if (dataEnabled[APN_DEFAULT_ID]) {
+            enabledCount++;
+        }
+        mAutoAttachOnCreation = dataEnabled[APN_DEFAULT_ID];
     }
 
-    public abstract void dispose();
+    public void dispose() {
+        mPhone.getContext().unregisterReceiver(this.mIntentReceiver);
+    }
 
     public Activity getActivity() {
-        return activity;
+        return mActivity;
     }
 
     public State getState() {
-        return state;
+        return mState;
     }
 
     public String getStateInString() {
-        switch (state) {
+        switch (mState) {
             case IDLE:          return "IDLE";
             case INITING:       return "INIT";
             case CONNECTING:    return "CING";
@@ -231,6 +338,14 @@
     }
 
     /**
+     * @return the data connections
+     */
+    public ArrayList<DataConnection> getAllDataConnections() {
+        /** TODO: change return type to Collection? */
+        return new ArrayList<DataConnection>(mDataConnections.values());
+    }
+
+    /**
      * The data connection is expected to be setup while device
      *  1. has Icc card
      *  2. registered for data service
@@ -246,9 +361,9 @@
     //  the shared values.  If it is not, then update it.
     public void setDataOnRoamingEnabled(boolean enabled) {
         if (getDataOnRoamingEnabled() != enabled) {
-            Settings.Secure.putInt(phone.getContext().getContentResolver(),
+            Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
                 Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
-            if (phone.getServiceState().getRoaming()) {
+            if (mPhone.getServiceState().getRoaming()) {
                 if (enabled) {
                     mRetryMgr.resetRetryCount();
                 }
@@ -257,16 +372,19 @@
         }
     }
 
-    //Retrieve the data roaming setting from the shared preferences.
+    // Retrieve the data roaming setting from the shared preferences.
     public boolean getDataOnRoamingEnabled() {
         try {
-            return Settings.Secure.getInt(phone.getContext().getContentResolver(),
-                Settings.Secure.DATA_ROAMING) > 0;
+            return Settings.Secure.getInt(
+                    mPhone.getContext().getContentResolver(), Settings.Secure.DATA_ROAMING) > 0;
         } catch (SettingNotFoundException snfe) {
             return false;
         }
     }
 
+
+    protected abstract String getActionIntentReconnectAlarm();
+
     // abstract handler methods
     protected abstract boolean onTrySetupData(String reason);
     protected abstract void onRoamingOff();
@@ -274,14 +392,14 @@
     protected abstract void onRadioAvailable();
     protected abstract void onRadioOffOrNotAvailable();
     protected abstract void onDataSetupComplete(AsyncResult ar);
-    protected abstract void onDisconnectDone(AsyncResult ar);
+    protected abstract void onDisconnectDone(int connId, AsyncResult ar);
     protected abstract void onResetDone(AsyncResult ar);
     protected abstract void onVoiceCallStarted();
     protected abstract void onVoiceCallEnded();
     protected abstract void onCleanUpConnection(boolean tearDown, String reason);
 
     @Override
-    public void handleMessage (Message msg) {
+    public void handleMessage(Message msg) {
         switch (msg.what) {
 
             case EVENT_ENABLE_NEW_APN:
@@ -291,7 +409,7 @@
             case EVENT_TRY_SETUP_DATA:
                 String reason = null;
                 if (msg.obj instanceof String) {
-                    reason = (String)msg.obj;
+                    reason = (String) msg.obj;
                 }
                 onTrySetupData(reason);
                 break;
@@ -316,12 +434,13 @@
                 break;
 
             case EVENT_DATA_SETUP_COMPLETE:
-                cidActive = msg.arg1;
+                mCidActive = msg.arg1;
                 onDataSetupComplete((AsyncResult) msg.obj);
                 break;
 
             case EVENT_DISCONNECT_DONE:
-                onDisconnectDone((AsyncResult) msg.obj);
+                log("DataConnectoinTracker.handleMessage: EVENT_DISCONNECT_DONE msg=" + msg);
+                onDisconnectDone(msg.arg1, (AsyncResult) msg.obj);
                 break;
 
             case EVENT_VOICE_CALL_STARTED:
@@ -334,7 +453,7 @@
 
             case EVENT_CLEAN_UP_CONNECTION:
                 boolean tearDown = (msg.arg1 == 0) ? false : true;
-                onCleanUpConnection(tearDown, (String)msg.obj);
+                onCleanUpConnection(tearDown, (String) msg.obj);
                 break;
 
             case EVENT_SET_MASTER_DATA_ENABLE:
@@ -354,8 +473,9 @@
 
     /**
      * Report the current state of data connectivity (enabled or disabled)
+     *
      * @return {@code false} if data connectivity has been explicitly disabled,
-     * {@code true} otherwise.
+     *         {@code true} otherwise.
      */
     public synchronized boolean getDataEnabled() {
         return dataEnabled[APN_DEFAULT_ID];
@@ -363,8 +483,9 @@
 
     /**
      * Report on whether data connectivity is enabled
+     *
      * @return {@code false} if data connectivity has been explicitly disabled,
-     * {@code true} otherwise.
+     *         {@code true} otherwise.
      */
     public boolean getAnyDataEnabled() {
         return (enabledCount != 0);
@@ -378,6 +499,8 @@
 
     protected abstract void log(String s);
 
+    protected abstract void loge(String s);
+
     protected int apnTypeToId(String type) {
         if (TextUtils.equals(type, Phone.APN_TYPE_DEFAULT)) {
             return APN_DEFAULT_ID;
@@ -407,7 +530,7 @@
         case APN_HIPRI_ID:
             return Phone.APN_TYPE_HIPRI;
         default:
-            Log.e(LOG_TAG, "Unknown id (" + id + ") in apnIdToType");
+            log("Unknown id (" + id + ") in apnIdToType");
             return Phone.APN_TYPE_DEFAULT;
         }
     }
@@ -420,8 +543,6 @@
 
     protected abstract String getActiveApnString();
 
-    public abstract ArrayList<DataConnection> getAllDataConnections();
-
     protected abstract void setState(State s);
 
     protected LinkProperties getLinkProperties(String apnType) {
@@ -467,33 +588,34 @@
     protected void notifyDataConnection(String reason) {
         for (int id = 0; id < APN_NUM_TYPES; id++) {
             if (dataEnabled[id]) {
-                phone.notifyDataConnection(reason, apnIdToType(id));
+                mPhone.notifyDataConnection(reason, apnIdToType(id));
             }
         }
         notifyDataAvailability(reason);
     }
 
-    // a new APN has gone active and needs to send events to catch up with the current condition
+    // a new APN has gone active and needs to send events to catch up with the
+    // current condition
     private void notifyApnIdUpToCurrent(String reason, int apnId) {
-        switch (state) {
+        switch (mState) {
             case IDLE:
             case INITING:
                 break;
             case CONNECTING:
             case SCANNING:
-                phone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTING);
+                mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTING);
                 break;
             case CONNECTED:
             case DISCONNECTING:
-                phone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTING);
-                phone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTED);
+                mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTING);
+                mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTED);
                 break;
         }
     }
 
     // since we normally don't send info to a disconnected APN, we need to do this specially
     private void notifyApnIdDisconnected(String reason, int apnId) {
-        phone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.DISCONNECTED);
+        mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.DISCONNECTED);
     }
 
     // disabled apn's still need avail/unavail notificiations - send them out
@@ -526,10 +648,10 @@
      * @return {@code true} if data connectivity is possible, {@code false} otherwise.
      */
     protected boolean isDataPossible() {
-        boolean possible = (isDataAllowed() &&
-            !(getDataEnabled() && (state == State.FAILED || state == State.IDLE)));
+        boolean possible = (isDataAllowed()
+                && !(getDataEnabled() && (mState == State.FAILED || mState == State.IDLE)));
         if (!possible && DBG && isDataAllowed()) {
-            log("Data not possible.  No coverage: dataState = " + state);
+            log("Data not possible.  No coverage: dataState = " + mState);
         }
         return possible;
     }
@@ -549,13 +671,13 @@
 
     /**
      * Ensure that we are connected to an APN of the specified type.
-     * @param type the APN type (currently the only valid values
-     * are {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL})
-     * @return the result of the operation. Success is indicated by
-     * a return value of either {@code Phone.APN_ALREADY_ACTIVE} or
-     * {@code Phone.APN_REQUEST_STARTED}. In the latter case, a broadcast
-     * will be sent by the ConnectivityManager when a connection to
-     * the APN has been established.
+     *
+     * @param type the APN type (currently the only valid values are
+     *            {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL})
+     * @return Success is indicated by {@code Phone.APN_ALREADY_ACTIVE} or
+     *         {@code Phone.APN_REQUEST_STARTED}. In the latter case, a
+     *         broadcast will be sent by the ConnectivityManager when a
+     *         connection to the APN has been established.
      */
     public synchronized int enableApnType(String type) {
         int id = apnTypeToId(type);
@@ -564,13 +686,12 @@
         }
 
         if (DBG) {
-            Log.d(LOG_TAG, "enableApnType(" + type + "), isApnTypeActive = "
-                    + isApnTypeActive(type) + ", isApnIdEnabled =" + isApnIdEnabled(id) +
-                    " and state = " + state);
+            log("enableApnType(" + type + "), isApnTypeActive = " + isApnTypeActive(type)
+                    + ", isApnIdEnabled =" + isApnIdEnabled(id) + " and state = " + mState);
         }
 
         if (!isApnTypeAvailable(type)) {
-            if (DBG) Log.d(LOG_TAG, "type not available");
+            if (DBG) log("type not available");
             return Phone.APN_TYPE_NOT_AVAILABLE;
         }
 
@@ -583,15 +704,21 @@
     }
 
     /**
-     * The APN of the specified type is no longer needed. Ensure that if
-     * use of the default APN has not been explicitly disabled, we are connected
-     * to the default APN.
+     * The APN of the specified type is no longer needed. Ensure that if use of
+     * the default APN has not been explicitly disabled, we are connected to the
+     * default APN.
+     *
      * @param type the APN type. The only valid values are currently
-     * {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}.
-     * @return
+     *            {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}.
+     * @return Success is indicated by {@code Phone.APN_ALREADY_ACTIVE} or
+     *         {@code Phone.APN_REQUEST_STARTED}. In the latter case, a
+     *         broadcast will be sent by the ConnectivityManager when a
+     *         connection to the APN has been disconnected. A {@code
+     *         Phone.APN_REQUEST_FAILED} is returned if the type parameter is
+     *         invalid or if the apn wasn't enabled.
      */
     public synchronized int disableApnType(String type) {
-        if (DBG) Log.d(LOG_TAG, "disableApnType("+type+")");
+        if (DBG) log("disableApnType(" + type + ")");
         int id = apnTypeToId(type);
         if (id == APN_INVALID_ID) {
             return Phone.APN_REQUEST_FAILED;
@@ -614,8 +741,8 @@
 
     private void setEnabled(int id, boolean enable) {
         if (DBG) {
-            Log.d(LOG_TAG, "setEnabled(" + id + ", " + enable + ") with old state = "
-                    + dataEnabled[id] + " and enabledCount = " + enabledCount);
+            log("setEnabled(" + id + ", " + enable + ") with old state = " + dataEnabled[id]
+                    + " and enabledCount = " + enabledCount);
         }
         Message msg = obtainMessage(EVENT_ENABLE_NEW_APN);
         msg.arg1 = id;
@@ -625,9 +752,10 @@
 
     protected synchronized void onEnableApn(int apnId, int enabled) {
         if (DBG) {
-            Log.d(LOG_TAG, "EVENT_APN_ENABLE_REQUEST " + apnId + ", " + enabled);
-            Log.d(LOG_TAG, " dataEnabled = " + dataEnabled[apnId] + ", enabledCount = "
-                    + enabledCount + ", isApnTypeActive = " + isApnTypeActive(apnIdToType(apnId)));
+            log("EVENT_APN_ENABLE_REQUEST apnId=" + apnId + ", apnType=" + apnIdToType(apnId) +
+                    ", enabled=" + enabled + ", dataEnabled = " + dataEnabled[apnId] +
+                    ", enabledCount = " + enabledCount + ", isApnTypeActive = " +
+                    isApnTypeActive(apnIdToType(apnId)));
         }
         if (enabled == ENABLED) {
             if (!dataEnabled[apnId]) {
@@ -676,18 +804,22 @@
     }
 
     /**
-     * Prevent mobile data connections from being established,
-     * or once again allow mobile data connections. If the state
-     * toggles, then either tear down or set up data, as
-     * appropriate to match the new state.
-     * <p>This operation only affects the default APN, and if the same APN is
-     * currently being used for MMS traffic, the teardown will not happen
-     * even when {@code enable} is {@code false}.</p>
-     * @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data
+     * Prevent mobile data connections from being established, or once again
+     * allow mobile data connections. If the state toggles, then either tear
+     * down or set up data, as appropriate to match the new state.
+     * <p>
+     * This operation only affects the default APN, and if the same APN is
+     * currently being used for MMS traffic, the teardown will not happen even
+     * when {@code enable} is {@code false}.
+     * </p>
+     *
+     * @param enable indicates whether to enable ({@code true}) or disable (
+     *            {@code false}) data
      * @return {@code true} if the operation succeeded
      */
     public boolean setDataEnabled(boolean enable) {
-        if (DBG) Log.d(LOG_TAG, "setDataEnabled(" + enable + ")");
+        if (DBG)
+            log("setDataEnabled(" + enable + ")");
 
         Message msg = obtainMessage(EVENT_SET_MASTER_DATA_ENABLE);
         msg.arg1 = (enable ? ENABLED : DISABLED);
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
index 95cb1c6..8072c44 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
@@ -23,6 +23,7 @@
 import com.android.internal.telephony.gsm.ApnSetting;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.RetryManager;
 
 /**
  * {@hide}
@@ -39,23 +40,27 @@
 
 
     // ***** Constructor
-    private CdmaDataConnection(CDMAPhone phone, String name) {
-        super(phone, name);
+    private CdmaDataConnection(CDMAPhone phone, String name, RetryManager rm) {
+        super(phone, name, rm);
     }
 
     /**
      * Create the connection object
      *
-     * @param phone
+     * @param phone the Phone
+     * @param id the connection id
+     * @param rm the RetryManager
      * @return CdmaDataConnection that was created.
      */
-    static CdmaDataConnection makeDataConnection(CDMAPhone phone) {
+    static CdmaDataConnection makeDataConnection(CDMAPhone phone, int id, RetryManager rm) {
         synchronized (mCountLock) {
             mCount += 1;
         }
-        CdmaDataConnection cdmaDc = new CdmaDataConnection(phone, "CdmaDataConnection-" + mCount);
+        CdmaDataConnection cdmaDc = new CdmaDataConnection(phone,
+                "CdmaDataConnection-" + mCount, rm);
         cdmaDc.start();
         if (DBG) cdmaDc.log("Made " + cdmaDc.getName());
+        cdmaDc.mId = id;
         return cdmaDc;
     }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index e499e95..7c652c5 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -18,21 +18,13 @@
 
 import android.app.AlarmManager;
 import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.net.IConnectivityManager;
-import android.net.NetworkInfo;
 import android.net.TrafficStats;
-import android.net.wifi.WifiManager;
 import android.os.AsyncResult;
 import android.os.Message;
-import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.preference.PreferenceManager;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.telephony.cdma.CdmaCellLocation;
@@ -46,6 +38,7 @@
 import com.android.internal.telephony.DataConnection;
 import com.android.internal.telephony.DataConnectionTracker;
 import com.android.internal.telephony.EventLogTags;
+import com.android.internal.telephony.RetryManager;
 import com.android.internal.telephony.gsm.ApnSetting;
 import com.android.internal.telephony.Phone;
 
@@ -59,20 +52,11 @@
 
     private CDMAPhone mCdmaPhone;
 
-    // Indicates baseband will not auto-attach
-    private boolean noAutoAttach = false;
-    private boolean mIsScreenOn = true;
-
     //useful for debugging
-    boolean failNextConnect = false;
+    boolean mFailNextConnect = false;
 
-    /**
-     * dataConnectionList holds all the Data connection
-     */
-    private ArrayList<DataConnection> dataConnectionList;
-
-    /** Currently active CdmaDataConnection */
-    private CdmaDataConnection mActiveDataConnection;
+    /** The DataConnection being setup */
+    private CdmaDataConnection mPendingDataConnection;
 
     private boolean mPendingRestartRadio = false;
     private static final int TIME_DELAYED_TO_RESTART_RADIO =
@@ -83,10 +67,8 @@
      */
     private static final int DATA_CONNECTION_POOL_SIZE = 1;
 
-    private static final int POLL_CONNECTION_MILLIS = 5 * 1000;
     private static final String INTENT_RECONNECT_ALARM =
-            "com.android.internal.telephony.cdma-reconnect";
-    private static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason";
+        "com.android.internal.telephony.cdma-reconnect";
 
     /**
      * Constants for the data connection activity:
@@ -110,49 +92,6 @@
     // if we have no active Apn this is null
     protected ApnSetting mActiveApn;
 
-    // Possibly promote to base class, the only difference is
-    // the INTENT_RECONNECT_ALARM action is a different string.
-    // Do consider technology changes if it is promoted.
-    BroadcastReceiver mIntentReceiver = new BroadcastReceiver ()
-    {
-        @Override
-        public void onReceive(Context context, Intent intent)
-        {
-            String action = intent.getAction();
-            if (action.equals(Intent.ACTION_SCREEN_ON)) {
-                mIsScreenOn = true;
-                stopNetStatPoll();
-                startNetStatPoll();
-            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
-                mIsScreenOn = false;
-                stopNetStatPoll();
-                startNetStatPoll();
-            } else if (action.equals((INTENT_RECONNECT_ALARM))) {
-                Log.d(LOG_TAG, "Data reconnect alarm. Previous state was " + state);
-
-                String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
-                if (state == State.FAILED) {
-                    cleanUpConnection(false, reason);
-                }
-                trySetupData(reason);
-            } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
-                final android.net.NetworkInfo networkInfo = (NetworkInfo)
-                        intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
-                mIsWifiConnected = (networkInfo != null && networkInfo.isConnected());
-            } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
-                final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
-                        WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
-
-                if (!enabled) {
-                    // when wifi got disabeled, the NETWORK_STATE_CHANGED_ACTION
-                    // quit and wont report disconnected til next enalbing.
-                    mIsWifiConnected = false;
-                }
-            }
-        }
-    };
-
-
     /* Constructor */
 
     CdmaDataConnectionTracker(CDMAPhone p) {
@@ -172,79 +111,49 @@
         p.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
         p.mCM.registerForCdmaOtaProvision(this, EVENT_CDMA_OTA_PROVISION, null);
 
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(INTENT_RECONNECT_ALARM);
-        filter.addAction(Intent.ACTION_SCREEN_ON);
-        filter.addAction(Intent.ACTION_SCREEN_OFF);
-        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
-        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
-
-        // TODO: Why is this registering the phone as the receiver of the intent
-        //       and not its own handler?
-        p.getContext().registerReceiver(mIntentReceiver, filter, null, p);
-
         mDataConnectionTracker = this;
 
         createAllDataConnectionList();
-
-        // This preference tells us 1) initial condition for "dataEnabled",
-        // and 2) whether the RIL will setup the baseband to auto-PS attach.
-        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
-
-        boolean dataEnabledSetting = true;
-        try {
-            dataEnabledSetting = IConnectivityManager.Stub.asInterface(ServiceManager.
-                    getService(Context.CONNECTIVITY_SERVICE)).getMobileDataEnabled();
-        } catch (Exception e) {
-            // nothing to do - use the old behavior and leave data on
-        }
-        dataEnabled[APN_DEFAULT_ID] =
-                !sp.getBoolean(CDMAPhone.DATA_DISABLED_ON_BOOT_KEY, false) &&
-                dataEnabledSetting;
-        if (dataEnabled[APN_DEFAULT_ID]) {
-            enabledCount++;
-        }
-        noAutoAttach = !dataEnabled[APN_DEFAULT_ID];
-
-        if (!mRetryMgr.configure(SystemProperties.get("ro.cdma.data_retry_config"))) {
-            if (!mRetryMgr.configure(DEFAULT_DATA_RETRY_CONFIG)) {
-                // Should never happen, log an error and default to a simple linear sequence.
-                Log.e(LOG_TAG, "Could not configure using DEFAULT_DATA_RETRY_CONFIG="
-                        + DEFAULT_DATA_RETRY_CONFIG);
-                mRetryMgr.configure(20, 2000, 1000);
-            }
-        }
     }
 
+    @Override
     public void dispose() {
+        super.dispose();
+
         // Unregister from all events
-        phone.mCM.unregisterForAvailable(this);
-        phone.mCM.unregisterForOffOrNotAvailable(this);
+        mPhone.mCM.unregisterForAvailable(this);
+        mPhone.mCM.unregisterForOffOrNotAvailable(this);
         mCdmaPhone.mRuimRecords.unregisterForRecordsLoaded(this);
-        phone.mCM.unregisterForNVReady(this);
-        phone.mCM.unregisterForDataStateChanged(this);
+        mPhone.mCM.unregisterForNVReady(this);
+        mPhone.mCM.unregisterForDataStateChanged(this);
         mCdmaPhone.mCT.unregisterForVoiceCallEnded(this);
         mCdmaPhone.mCT.unregisterForVoiceCallStarted(this);
         mCdmaPhone.mSST.unregisterForCdmaDataConnectionAttached(this);
         mCdmaPhone.mSST.unregisterForCdmaDataConnectionDetached(this);
         mCdmaPhone.mSST.unregisterForRoamingOn(this);
         mCdmaPhone.mSST.unregisterForRoamingOff(this);
-        phone.mCM.unregisterForCdmaOtaProvision(this);
+        mPhone.mCM.unregisterForCdmaOtaProvision(this);
 
-        phone.getContext().unregisterReceiver(this.mIntentReceiver);
         destroyAllDataConnectionList();
     }
 
+    @Override
     protected void finalize() {
-        if(DBG) Log.d(LOG_TAG, "CdmaDataConnectionTracker finalized");
+        if(DBG) log("CdmaDataConnectionTracker finalized");
     }
 
+    @Override
+    protected String getActionIntentReconnectAlarm() {
+        return INTENT_RECONNECT_ALARM;
+    }
+
+    @Override
     protected void setState(State s) {
         if (DBG) log ("setState: " + s);
-        if (state != s) {
+        if (mState != s) {
             EventLog.writeEvent(EventLogTags.CDMA_DATA_STATE_CHANGE,
-                    state.toString(), s.toString());
-            state = s;
+                    mState.toString(), s.toString());
+            mState = s;
         }
     }
 
@@ -263,6 +172,7 @@
         return false;
     }
 
+    @Override
     protected String[] getActiveApnTypes() {
         String[] result;
         if (mActiveApn != null) {
@@ -274,6 +184,7 @@
         return result;
     }
 
+    @Override
     protected String getActiveApnString() {
         return null;
     }
@@ -287,45 +198,51 @@
      *
      * @return false while no data connection if all above requirements are met.
      */
+    @Override
     public boolean isDataConnectionAsDesired() {
-        boolean roaming = phone.getServiceState().getRoaming();
+        boolean roaming = mPhone.getServiceState().getRoaming();
 
-        if (((phone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) ||
+        if (((mPhone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) ||
                  mCdmaPhone.mRuimRecords.getRecordsLoaded()) &&
                 (mCdmaPhone.mSST.getCurrentCdmaDataConnectionState() ==
                  ServiceState.STATE_IN_SERVICE) &&
                 (!roaming || getDataOnRoamingEnabled()) &&
                 !mIsWifiConnected ) {
-            return (state == State.CONNECTED);
+            return (mState == State.CONNECTED);
         }
         return true;
     }
 
+    @Override
     protected boolean isDataAllowed() {
         int psState = mCdmaPhone.mSST.getCurrentCdmaDataConnectionState();
-        boolean roaming = (phone.getServiceState().getRoaming() && !getDataOnRoamingEnabled());
+        boolean roaming = (mPhone.getServiceState().getRoaming() && !getDataOnRoamingEnabled());
         boolean desiredPowerState = mCdmaPhone.mSST.getDesiredPowerState();
 
-        boolean allowed = (psState == ServiceState.STATE_IN_SERVICE &&
-                (phone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY ||
-                 mCdmaPhone.mRuimRecords.getRecordsLoaded()) &&
-                (mCdmaPhone.mSST.isConcurrentVoiceAndData() ||
-                 phone.getState() == Phone.State.IDLE) &&
-                !roaming &&
-                mMasterDataEnabled &&
-                desiredPowerState &&
-                !mPendingRestartRadio &&
-                !mCdmaPhone.needsOtaServiceProvisioning());
+        boolean allowed =
+                    (psState == ServiceState.STATE_IN_SERVICE ||
+                            mAutoAttachOnCreation) &&
+                    (mPhone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY ||
+                            mCdmaPhone.mRuimRecords.getRecordsLoaded()) &&
+                    (mCdmaPhone.mSST.isConcurrentVoiceAndData() ||
+                            mPhone.getState() == Phone.State.IDLE) &&
+                    !roaming &&
+                    mMasterDataEnabled &&
+                    desiredPowerState &&
+                    !mPendingRestartRadio &&
+                    !mCdmaPhone.needsOtaServiceProvisioning();
         if (!allowed && DBG) {
             String reason = "";
-            if (psState != ServiceState.STATE_IN_SERVICE) reason += " - psState= " + psState;
-            if (phone.mCM.getRadioState() != CommandsInterface.RadioState.NV_READY &&
-                    !mCdmaPhone.mRuimRecords.getRecordsLoaded()) {
-                reason += " - radioState= " + phone.mCM.getRadioState() + " - RUIM not loaded";
+            if (!((psState == ServiceState.STATE_IN_SERVICE) || mAutoAttachOnCreation)) {
+                reason += " - psState= " + psState;
             }
-            if (phone.getState() != Phone.State.IDLE &&
+            if (!(mPhone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY ||
+                    mCdmaPhone.mRuimRecords.getRecordsLoaded())) {
+                reason += " - radioState= " + mPhone.mCM.getRadioState() + " - RUIM not loaded";
+            }
+            if (mPhone.getState() != Phone.State.IDLE &&
                     mCdmaPhone.mSST.isConcurrentVoiceAndData()) {
-                reason += " - concurrentVoiceAndData not allowed and state= " + phone.getState();
+                reason += " - concurrentVoiceAndData not allowed and state= " + mPhone.getState();
             }
             if (roaming) reason += " - Roaming";
             if (!mMasterDataEnabled) reason += " - mMasterDataEnabled= false";
@@ -340,22 +257,22 @@
     private boolean trySetupData(String reason) {
         if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason));
 
-        if (phone.getSimulatedRadioControl() != null) {
+        if (mPhone.getSimulatedRadioControl() != null) {
             // Assume data is connected on the simulator
             // FIXME  this can be improved
             setState(State.CONNECTED);
             notifyDataConnection(reason);
             notifyOffApnsOfAvailability(reason, true);
 
-            Log.i(LOG_TAG, "(fix?) We're on the simulator; assuming data is connected");
+            log("(fix?) We're on the simulator; assuming data is connected");
             return true;
         }
 
         int psState = mCdmaPhone.mSST.getCurrentCdmaDataConnectionState();
-        boolean roaming = phone.getServiceState().getRoaming();
+        boolean roaming = mPhone.getServiceState().getRoaming();
         boolean desiredPowerState = mCdmaPhone.mSST.getDesiredPowerState();
 
-        if ((state == State.IDLE || state == State.SCANNING) &&
+        if ((mState == State.IDLE || mState == State.SCANNING) &&
                 isDataAllowed() && getAnyDataEnabled()) {
             boolean retValue = setupData(reason);
             notifyOffApnsOfAvailability(reason, retValue);
@@ -367,13 +284,12 @@
     }
 
     /**
-     * If tearDown is true, this only tears down a CONNECTED session. Presently,
-     * there is no mechanism for abandoning an INITING/CONNECTING session,
-     * but would likely involve cancelling pending async requests or
-     * setting a flag or new state to ignore them when they came in
-     * @param tearDown true if the underlying DataConnection should be
-     * disconnected.
-     * @param reason reason for the clean up.
+     * Cleanup all connections.
+     *
+     * TODO: Cleanup only a specified connection passed as a parameter.
+     *
+     * @param tearDown true if the underlying DataConnection should be disconnected.
+     * @param reason for the clean up.
      */
     private void cleanUpConnection(boolean tearDown, String reason) {
         if (DBG) log("cleanUpConnection: reason: " + reason);
@@ -381,7 +297,7 @@
         // Clear the reconnect alarm, if set.
         if (mReconnectIntent != null) {
             AlarmManager am =
-                (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
+                (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
             am.cancel(mReconnectIntent);
             mReconnectIntent = null;
         }
@@ -390,11 +306,12 @@
         notifyDataAvailability(reason);
 
         boolean notificationDeferred = false;
-        for (DataConnection conn : dataConnectionList) {
+        for (DataConnection conn : mDataConnections.values()) {
             if(conn != null) {
                 if (tearDown) {
                     if (DBG) log("cleanUpConnection: teardown, call conn.disconnect");
-                    conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE, reason));
+                    conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE,
+                            conn.getDataConnectionId(), 0, reason));
                     notificationDeferred = true;
                 } else {
                     if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously");
@@ -413,10 +330,9 @@
     }
 
     private CdmaDataConnection findFreeDataConnection() {
-        for (DataConnection connBase : dataConnectionList) {
-            CdmaDataConnection conn = (CdmaDataConnection) connBase;
-            if (conn.isInactive()) {
-                return conn;
+        for (DataConnection dc : mDataConnections.values()) {
+            if (dc.isInactive()) {
+                return (CdmaDataConnection) dc;
             }
         }
         return null;
@@ -430,7 +346,8 @@
             return false;
         }
 
-        mActiveDataConnection = conn;
+        /** TODO: We probably want the connection being setup to a parameter passed around */
+        mPendingDataConnection = conn;
         String[] types;
         if (mRequestedApnType.equals(Phone.APN_TYPE_DUN)) {
             types = new String[1];
@@ -458,28 +375,31 @@
     }
 
     private void resetPollStats() {
-        txPkts = -1;
-        rxPkts = -1;
-        sentSinceLastRecv = 0;
-        netStatPollPeriod = POLL_NETSTAT_MILLIS;
+        mTxPkts = -1;
+        mRxPkts = -1;
+        mSentSinceLastRecv = 0;
+        mNetStatPollPeriod = POLL_NETSTAT_MILLIS;
         mNoRecvPollCount = 0;
     }
 
+    @Override
     protected void startNetStatPoll() {
-        if (state == State.CONNECTED && netStatPollEnabled == false) {
-            Log.d(LOG_TAG, "[DataConnection] Start poll NetStat");
+        if (mState == State.CONNECTED && mNetStatPollEnabled == false) {
+            log("[DataConnection] Start poll NetStat");
             resetPollStats();
-            netStatPollEnabled = true;
+            mNetStatPollEnabled = true;
             mPollNetStat.run();
         }
     }
 
+    @Override
     protected void stopNetStatPoll() {
-        netStatPollEnabled = false;
+        mNetStatPollEnabled = false;
         removeCallbacks(mPollNetStat);
-        Log.d(LOG_TAG, "[DataConnection] Stop poll NetStat");
+        log("[DataConnection] Stop poll NetStat");
     }
 
+    @Override
     protected void restartRadio() {
         if (DBG) log("Cleanup connection and wait " +
                 (TIME_DELAYED_TO_RESTART_RADIO / 1000) + "s to restart radio");
@@ -496,73 +416,73 @@
 
             Activity newActivity;
 
-            preTxPkts = txPkts;
-            preRxPkts = rxPkts;
+            preTxPkts = mTxPkts;
+            preRxPkts = mRxPkts;
 
-            txPkts = TrafficStats.getMobileTxPackets();
-            rxPkts = TrafficStats.getMobileRxPackets();
+            mTxPkts = TrafficStats.getMobileTxPackets();
+            mRxPkts = TrafficStats.getMobileRxPackets();
 
-            //Log.d(LOG_TAG, "rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts));
+            //log("rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts));
 
-            if (netStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) {
-                sent = txPkts - preTxPkts;
-                received = rxPkts - preRxPkts;
+            if (mNetStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) {
+                sent = mTxPkts - preTxPkts;
+                received = mRxPkts - preRxPkts;
 
                 if ( sent > 0 && received > 0 ) {
-                    sentSinceLastRecv = 0;
+                    mSentSinceLastRecv = 0;
                     newActivity = Activity.DATAINANDOUT;
                 } else if (sent > 0 && received == 0) {
-                    if (phone.getState()  == Phone.State.IDLE) {
-                        sentSinceLastRecv += sent;
+                    if (mPhone.getState()  == Phone.State.IDLE) {
+                        mSentSinceLastRecv += sent;
                     } else {
-                        sentSinceLastRecv = 0;
+                        mSentSinceLastRecv = 0;
                     }
                     newActivity = Activity.DATAOUT;
                 } else if (sent == 0 && received > 0) {
-                    sentSinceLastRecv = 0;
+                    mSentSinceLastRecv = 0;
                     newActivity = Activity.DATAIN;
                 } else if (sent == 0 && received == 0) {
-                    newActivity = (activity == Activity.DORMANT) ? activity : Activity.NONE;
+                    newActivity = (mActivity == Activity.DORMANT) ? mActivity : Activity.NONE;
                 } else {
-                    sentSinceLastRecv = 0;
-                    newActivity = (activity == Activity.DORMANT) ? activity : Activity.NONE;
+                    mSentSinceLastRecv = 0;
+                    newActivity = (mActivity == Activity.DORMANT) ? mActivity : Activity.NONE;
                 }
 
-                if (activity != newActivity) {
-                    activity = newActivity;
-                    phone.notifyDataActivity();
+                if (mActivity != newActivity && mIsScreenOn) {
+                    mActivity = newActivity;
+                    mPhone.notifyDataActivity();
                 }
             }
 
-            if (sentSinceLastRecv >= NUMBER_SENT_PACKETS_OF_HANG) {
+            if (mSentSinceLastRecv >= NUMBER_SENT_PACKETS_OF_HANG) {
                 // Packets sent without ack exceeded threshold.
 
                 if (mNoRecvPollCount == 0) {
                     EventLog.writeEvent(
                             EventLogTags.PDP_RADIO_RESET_COUNTDOWN_TRIGGERED,
-                            sentSinceLastRecv);
+                            mSentSinceLastRecv);
                 }
 
                 if (mNoRecvPollCount < NO_RECV_POLL_LIMIT) {
                     mNoRecvPollCount++;
                     // Slow down the poll interval to let things happen
-                    netStatPollPeriod = POLL_NETSTAT_SLOW_MILLIS;
+                    mNetStatPollPeriod = POLL_NETSTAT_SLOW_MILLIS;
                 } else {
-                    if (DBG) log("Sent " + String.valueOf(sentSinceLastRecv) +
+                    if (DBG) log("Sent " + String.valueOf(mSentSinceLastRecv) +
                                         " pkts since last received");
                     // We've exceeded the threshold.  Restart the radio.
-                    netStatPollEnabled = false;
+                    mNetStatPollEnabled = false;
                     stopNetStatPoll();
                     restartRadio();
                     EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, NO_RECV_POLL_LIMIT);
                 }
             } else {
                 mNoRecvPollCount = 0;
-                netStatPollPeriod = POLL_NETSTAT_MILLIS;
+                mNetStatPollPeriod = POLL_NETSTAT_MILLIS;
             }
 
-            if (netStatPollEnabled) {
-                mDataConnectionTracker.postDelayed(this, netStatPollPeriod);
+            if (mNetStatPollEnabled) {
+                mDataConnectionTracker.postDelayed(this, mNetStatPollPeriod);
             }
         }
     };
@@ -594,7 +514,7 @@
     }
 
     private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
-        if (state == State.FAILED) {
+        if (mState == State.FAILED) {
             /**
              * For now With CDMA we never try to reconnect on
              * error and instead just continue to retry
@@ -602,15 +522,15 @@
              * TODO: Make this configurable?
              */
             int nextReconnectDelay = mRetryMgr.getRetryTimer();
-            Log.d(LOG_TAG, "Data Connection activate failed. Scheduling next attempt for "
+            log("Data Connection activate failed. Scheduling next attempt for "
                     + (nextReconnectDelay / 1000) + "s");
 
             AlarmManager am =
-                (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
+                (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
             Intent intent = new Intent(INTENT_RECONNECT_ALARM);
             intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, reason);
             mReconnectIntent = PendingIntent.getBroadcast(
-                    phone.getContext(), 0, intent, 0);
+                    mPhone.getContext(), 0, intent, 0);
             am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                     SystemClock.elapsedRealtime() + nextReconnectDelay,
                     mReconnectIntent);
@@ -618,7 +538,7 @@
             mRetryMgr.increaseRetryCount();
 
             if (!shouldPostNotification(lastFailCauseCode)) {
-                Log.d(LOG_TAG,"NOT Posting Data Connection Unavailable notification "
+                log("NOT Posting Data Connection Unavailable notification "
                                 + "-- likely transient error");
             } else {
                 notifyNoData(lastFailCauseCode);
@@ -639,14 +559,14 @@
     }
 
     protected void onRecordsLoaded() {
-        if (state == State.FAILED) {
+        if (mState == State.FAILED) {
             cleanUpConnection(false, null);
         }
         sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, Phone.REASON_SIM_LOADED));
     }
 
     protected void onNVReady() {
-        if (state == State.FAILED) {
+        if (mState == State.FAILED) {
             cleanUpConnection(false, null);
         }
         sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
@@ -657,12 +577,13 @@
      */
     @Override
     protected void onEnableNewApn() {
-          cleanUpConnection(true, Phone.REASON_APN_SWITCHED);
+        cleanUpConnection(true, Phone.REASON_APN_SWITCHED);
     }
 
     /**
      * @override com.android.internal.telephony.DataConnectionTracker
      */
+    @Override
     protected boolean onTrySetupData(String reason) {
         return trySetupData(reason);
     }
@@ -670,6 +591,7 @@
     /**
      * @override com.android.internal.telephony.DataConnectionTracker
      */
+    @Override
     protected void onRoamingOff() {
         trySetupData(Phone.REASON_ROAMING_OFF);
     }
@@ -677,6 +599,7 @@
     /**
      * @override com.android.internal.telephony.DataConnectionTracker
      */
+    @Override
     protected void onRoamingOn() {
         if (getDataOnRoamingEnabled()) {
             trySetupData(Phone.REASON_ROAMING_ON);
@@ -689,19 +612,20 @@
     /**
      * @override com.android.internal.telephony.DataConnectionTracker
      */
+    @Override
     protected void onRadioAvailable() {
-        if (phone.getSimulatedRadioControl() != null) {
+        if (mPhone.getSimulatedRadioControl() != null) {
             // Assume data is connected on the simulator
             // FIXME  this can be improved
             setState(State.CONNECTED);
             notifyDataConnection(null);
 
-            Log.i(LOG_TAG, "We're on the simulator; assuming data is connected");
+            log("We're on the simulator; assuming data is connected");
         }
 
         notifyDataAvailability(null);
 
-        if (state != State.IDLE) {
+        if (mState != State.IDLE) {
             cleanUpConnection(true, null);
         }
     }
@@ -709,13 +633,14 @@
     /**
      * @override com.android.internal.telephony.DataConnectionTracker
      */
+    @Override
     protected void onRadioOffOrNotAvailable() {
         mRetryMgr.resetRetryCount();
 
-        if (phone.getSimulatedRadioControl() != null) {
+        if (mPhone.getSimulatedRadioControl() != null) {
             // Assume data is connected on the simulator
             // FIXME  this can be improved
-            Log.i(LOG_TAG, "We're on the simulator; assuming radio off is meaningless");
+            log("We're on the simulator; assuming radio off is meaningless");
         } else {
             if (DBG) log("Radio is off and clean up all connection");
             cleanUpConnection(false, Phone.REASON_RADIO_TURNED_OFF);
@@ -725,6 +650,7 @@
     /**
      * @override com.android.internal.telephony.DataConnectionTracker
      */
+    @Override
     protected void onDataSetupComplete(AsyncResult ar) {
         String reason = null;
         if (ar.userObj instanceof String) {
@@ -733,8 +659,8 @@
 
         if (ar.exception == null) {
             // TODO: We should clear LinkProperties/Capabilities when torn down or disconnected
-            mLinkProperties = getLinkProperties(mActiveDataConnection);
-            mLinkCapabilities = getLinkCapabilities(mActiveDataConnection);
+            mLinkProperties = getLinkProperties(mPendingDataConnection);
+            mLinkCapabilities = getLinkCapabilities(mPendingDataConnection);
 
             // everything is setup
             notifyDefaultData(reason);
@@ -754,8 +680,9 @@
     /**
      * Called when EVENT_DISCONNECT_DONE is received.
      */
-    protected void onDisconnectDone(AsyncResult ar) {
-        if(DBG) log("EVENT_DISCONNECT_DONE");
+    @Override
+    protected void onDisconnectDone(int connId, AsyncResult ar) {
+        if(DBG) log("EVENT_DISCONNECT_DONE connId=" + connId);
         String reason = null;
         if (ar.userObj instanceof String) {
             reason = (String) ar.userObj;
@@ -799,8 +726,9 @@
     /**
      * @override com.android.internal.telephony.DataConnectionTracker
      */
+    @Override
     protected void onVoiceCallStarted() {
-        if (state == State.CONNECTED && !mCdmaPhone.mSST.isConcurrentVoiceAndData()) {
+        if (mState == State.CONNECTED && !mCdmaPhone.mSST.isConcurrentVoiceAndData()) {
             stopNetStatPoll();
             notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
             notifyDataAvailability(Phone.REASON_VOICE_CALL_STARTED);
@@ -810,8 +738,9 @@
     /**
      * @override com.android.internal.telephony.DataConnectionTracker
      */
+    @Override
     protected void onVoiceCallEnded() {
-        if (state == State.CONNECTED) {
+        if (mState == State.CONNECTED) {
             if (!mCdmaPhone.mSST.isConcurrentVoiceAndData()) {
                 startNetStatPoll();
                 notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
@@ -827,39 +756,49 @@
         }
     }
 
-    /**
-     * @override com.android.internal.telephony.DataConnectionTracker
-     */
+    @Override
     protected void onCleanUpConnection(boolean tearDown, String reason) {
         cleanUpConnection(tearDown, reason);
     }
 
     private void createAllDataConnectionList() {
-       dataConnectionList = new ArrayList<DataConnection>();
         CdmaDataConnection dataConn;
 
-       for (int i = 0; i < DATA_CONNECTION_POOL_SIZE; i++) {
-            dataConn = CdmaDataConnection.makeDataConnection(mCdmaPhone);
-            dataConnectionList.add(dataConn);
-       }
+        /** TODO: Use one retry manager for all connections for now */
+        RetryManager rm = mRetryMgr;
+        if (!rm.configure(SystemProperties.get("ro.cdma.data_retry_config"))) {
+            if (!rm.configure(DEFAULT_DATA_RETRY_CONFIG)) {
+                // Should never happen, log an error and default to a simple linear sequence.
+                log("Could not configure using DEFAULT_DATA_RETRY_CONFIG="
+                        + DEFAULT_DATA_RETRY_CONFIG);
+                rm.configure(20, 2000, 1000);
+            }
+        }
+
+        for (int i = 0; i < DATA_CONNECTION_POOL_SIZE; i++) {
+            int id = mUniqueIdGenerator.getAndIncrement();
+
+            dataConn = CdmaDataConnection.makeDataConnection(mCdmaPhone, id, rm);
+            mDataConnections.put(id, dataConn);
+        }
     }
 
     private void destroyAllDataConnectionList() {
-        if(dataConnectionList != null) {
-            dataConnectionList.removeAll(dataConnectionList);
+        if(mDataConnections != null) {
+            mDataConnections.clear();
         }
     }
 
     private void onCdmaDataDetached() {
-        if (state == State.CONNECTED) {
+        if (mState == State.CONNECTED) {
             startNetStatPoll();
             notifyDataConnection(Phone.REASON_CDMA_DATA_DETACHED);
         } else {
-            if (state == State.FAILED) {
+            if (mState == State.FAILED) {
                 cleanUpConnection(false, Phone.REASON_CDMA_DATA_DETACHED);
                 mRetryMgr.resetRetryCount();
 
-                CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation());
+                CdmaCellLocation loc = (CdmaCellLocation)(mPhone.getCellLocation());
                 EventLog.writeEvent(EventLogTags.CDMA_DATA_SETUP_FAILED,
                         loc != null ? loc.getBaseStationId() : -1,
                         TelephonyManager.getDefault().getNetworkType());
@@ -886,8 +825,8 @@
 
     private void onRestartRadio() {
         if (mPendingRestartRadio) {
-            Log.d(LOG_TAG, "************TURN OFF RADIO**************");
-            phone.mCM.setRadioPower(false, null);
+            log("************TURN OFF RADIO**************");
+            mPhone.mCM.setRadioPower(false, null);
             /* 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
@@ -900,7 +839,7 @@
     }
 
     private void writeEventLogCdmaDataDrop() {
-        CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation());
+        CdmaCellLocation loc = (CdmaCellLocation)(mPhone.getCellLocation());
         EventLog.writeEvent(EventLogTags.CDMA_DATA_DROP,
                 loc != null ? loc.getBaseStationId() : -1,
                 TelephonyManager.getDefault().getNetworkType());
@@ -916,7 +855,7 @@
             return;
         }
 
-        if (state == State.CONNECTED) {
+        if (mState == State.CONNECTED) {
             boolean isActiveOrDormantConnectionPresent = false;
             int connectionState = DATA_CONNECTION_ACTIVE_PH_LINK_INACTIVE;
 
@@ -932,7 +871,7 @@
 
             if (!isActiveOrDormantConnectionPresent) {
                 // No active or dormant connection
-                Log.i(LOG_TAG, "onDataStateChanged: No active connection"
+                log("onDataStateChanged: No active connection"
                         + "state is CONNECTED, disconnecting/cleanup");
                 writeEventLogCdmaDataDrop();
                 cleanUpConnection(true, null);
@@ -941,42 +880,39 @@
 
             switch (connectionState) {
                 case DATA_CONNECTION_ACTIVE_PH_LINK_UP:
-                    Log.v(LOG_TAG, "onDataStateChanged: active=LINK_ACTIVE && CONNECTED, ignore");
-                    activity = Activity.NONE;
-                    phone.notifyDataActivity();
+                    log("onDataStateChanged: active=LINK_ACTIVE && CONNECTED, ignore");
+                    mActivity = Activity.NONE;
+                    mPhone.notifyDataActivity();
                     startNetStatPoll();
                     break;
 
                 case DATA_CONNECTION_ACTIVE_PH_LINK_DOWN:
-                    Log.v(LOG_TAG, "onDataStateChanged active=LINK_DOWN && CONNECTED, dormant");
-                    activity = Activity.DORMANT;
-                    phone.notifyDataActivity();
+                    log("onDataStateChanged active=LINK_DOWN && CONNECTED, dormant");
+                    mActivity = Activity.DORMANT;
+                    mPhone.notifyDataActivity();
                     stopNetStatPoll();
                     break;
 
                 default:
-                    Log.v(LOG_TAG, "onDataStateChanged: IGNORE unexpected DataCallState.active="
+                    log("onDataStateChanged: IGNORE unexpected DataCallState.active="
                             + connectionState);
             }
         } else {
             // TODO: Do we need to do anything?
-            Log.i(LOG_TAG, "onDataStateChanged: not connected, state=" + state + " ignoring");
+            log("onDataStateChanged: not connected, state=" + mState + " ignoring");
         }
     }
 
-    public ArrayList<DataConnection> getAllDataConnections() {
-        return dataConnectionList;
-    }
-
     private void startDelayedRetry(FailCause cause, String reason) {
         notifyNoData(cause);
         reconnectAfterFail(cause, reason);
     }
 
+    @Override
     public void handleMessage (Message msg) {
 
-        if (!phone.mIsTheCurrentActivePhone) {
-            Log.d(LOG_TAG, "Ignore CDMA msgs since CDMA phone is inactive");
+        if (!mPhone.mIsTheCurrentActivePhone) {
+            log("Ignore CDMA msgs since CDMA phone is inactive");
             return;
         }
 
@@ -1013,7 +949,13 @@
         }
     }
 
+    @Override
     protected void log(String s) {
         Log.d(LOG_TAG, "[CdmaDataConnectionTracker] " + s);
     }
+
+    @Override
+    protected void loge(String s) {
+        Log.e(LOG_TAG, "[CdmaDataConnectionTracker] " + s);
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
index 1572f09..d428099 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
@@ -23,6 +23,7 @@
 import com.android.internal.telephony.DataConnection;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.RetryManager;
 
 /**
  * {@hide}
@@ -53,23 +54,27 @@
     private ApnSetting apn;
 
     //***** Constructor
-    private GsmDataConnection(GSMPhone phone, String name) {
-        super(phone, name);
+    private GsmDataConnection(GSMPhone phone, String name, RetryManager rm) {
+        super(phone, name, rm);
     }
 
     /**
      * Create the connection object
      *
-     * @param phone
+     * @param phone the Phone
+     * @param id the connection id
+     * @param rm the RetryManager
      * @return GsmDataConnection that was created.
      */
-    static GsmDataConnection makeDataConnection(GSMPhone phone) {
+    static GsmDataConnection makeDataConnection(GSMPhone phone, int id, RetryManager rm) {
         synchronized (mCountLock) {
             mCount += 1;
         }
-        GsmDataConnection gsmDc = new GsmDataConnection(phone, "GsmDataConnection-" + mCount);
+        GsmDataConnection gsmDc = new GsmDataConnection(phone, "GsmDataConnection-" + mCount, rm);
         gsmDc.start();
         if (DBG) gsmDc.log("Made " + gsmDc.getName());
+        gsmDc.mId = id;
+        gsmDc.mRetryMgr = rm;
         return gsmDc;
     }
 
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 66da6e8..2aca9ad 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -18,27 +18,19 @@
 
 import android.app.AlarmManager;
 import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
 import android.database.ContentObserver;
 import android.database.Cursor;
-import android.net.IConnectivityManager;
-import android.net.NetworkInfo;
 import android.net.ProxyProperties;
 import android.net.TrafficStats;
 import android.net.Uri;
-import android.net.wifi.WifiManager;
 import android.os.AsyncResult;
 import android.os.Message;
-import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.preference.PreferenceManager;
 import android.provider.Settings;
 import android.provider.Telephony;
 import android.telephony.ServiceState;
@@ -61,6 +53,7 @@
 import java.net.InetSocketAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
+import java.util.HashMap;
 
 /**
  * {@hide}
@@ -85,9 +78,6 @@
 
     //***** Instance Variables
 
-    // Indicates baseband will not auto-attach
-    private boolean noAutoAttach = false;
-
     private boolean mReregisterOnReconnectFailure = false;
     private ContentResolver mResolver;
 
@@ -95,13 +85,12 @@
     // Count of PDP reset attempts; reset when we see incoming,
     // call reRegisterNetwork, or pingTest succeeds.
     private int mPdpResetCount = 0;
-    private boolean mIsScreenOn = true;
 
     /** Delay between APN attempts */
     protected static final int APN_DELAY_MILLIS = 5000;
 
     //useful for debugging
-    boolean failNextConnect = false;
+    boolean mFailNextConnect = false;
 
     /**
      * allApns holds all apns for this sim spn, retrieved from
@@ -109,104 +98,49 @@
      *
      * Create once after simcard info is loaded
      */
-    private ArrayList<ApnSetting> allApns = null;
+    private ArrayList<ApnSetting> mAllApns = null;
 
     /**
      * waitingApns holds all apns that are waiting to be connected
      *
      * It is a subset of allApns and has the same format
      */
-    private ArrayList<ApnSetting> waitingApns = null;
+    private ArrayList<ApnSetting> mWaitingApns = null;
 
-    private ApnSetting preferredApn = null;
+    private ApnSetting mPreferredApn = null;
 
     /* Currently active APN */
     protected ApnSetting mActiveApn;
 
-    /**
-     * pdpList holds all the PDP connection, i.e. IP Link in GPRS
-     */
-    private ArrayList<DataConnection> pdpList;
+      /** The DataConnection being setup */
+    private GsmDataConnection mPendingDataConnection;
 
-    /** Currently active DataConnection */
-    private GsmDataConnection mActivePdp;
+    /** Convert an ApnType string to Id (TODO: Use "enumeration" instead of String for ApnType) */
+    private HashMap<String, Integer> mApnToDataConnectionId =
+                                    new HashMap<String, Integer>();
 
     /** Is packet service restricted by network */
     private boolean mIsPsRestricted = false;
 
     //***** Constants
 
-    // TODO: Increase this to match the max number of simultaneous
-    // PDP contexts we plan to support.
-    /**
-     * Pool size of DataConnection objects.
-     */
-    private static final int PDP_CONNECTION_POOL_SIZE = 1;
-
     private static final int POLL_PDP_MILLIS = 5 * 1000;
 
     private static final String INTENT_RECONNECT_ALARM = "com.android.internal.telephony.gprs-reconnect";
-    private static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason";
 
     static final Uri PREFERAPN_URI = Uri.parse("content://telephony/carriers/preferapn");
     static final String APN_ID = "apn_id";
     private boolean canSetPreferApn = false;
 
-    // for tracking retries on the default APN
-    private RetryManager mDefaultRetryManager;
-    // for tracking retries on a secondary APN
-    private RetryManager mSecondaryRetryManager;
-
-    BroadcastReceiver mIntentReceiver = new BroadcastReceiver ()
-    {
-        @Override
-        public void onReceive(Context context, Intent intent)
-        {
-            String action = intent.getAction();
-            if (action.equals(Intent.ACTION_SCREEN_ON)) {
-                mIsScreenOn = true;
-                stopNetStatPoll();
-                startNetStatPoll();
-            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
-                mIsScreenOn = false;
-                stopNetStatPoll();
-                startNetStatPoll();
-            } else if (action.equals((INTENT_RECONNECT_ALARM))) {
-                Log.d(LOG_TAG, "GPRS reconnect alarm. Previous state was " + state);
-
-                String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
-                if (state == State.FAILED) {
-                    Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
-                    msg.arg1 = 0; // tearDown is false
-                    msg.obj = (String) reason;
-                    sendMessage(msg);
-                }
-                sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
-            } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
-                final android.net.NetworkInfo networkInfo = (NetworkInfo)
-                        intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
-                mIsWifiConnected = (networkInfo != null && networkInfo.isConnected());
-            } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
-                final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
-                        WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
-
-                if (!enabled) {
-                    // when wifi got disabled, the NETWORK_STATE_CHANGED_ACTION
-                    // quit and won't report disconnected til next enabling.
-                    mIsWifiConnected = false;
-                }
-            }
-        }
-    };
-
     /** Watches for changes to the APN db. */
-    private ApnChangeObserver apnObserver;
+    private ApnChangeObserver mApnObserver;
 
     //***** Constructor
 
     GsmDataConnectionTracker(GSMPhone p) {
         super(p);
         mGsmPhone = p;
+
         p.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null);
         p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
         p.mSIMRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
@@ -220,73 +154,26 @@
         p.mSST.registerForPsRestrictedEnabled(this, EVENT_PS_RESTRICT_ENABLED, null);
         p.mSST.registerForPsRestrictedDisabled(this, EVENT_PS_RESTRICT_DISABLED, null);
 
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(INTENT_RECONNECT_ALARM);
-        filter.addAction(Intent.ACTION_SCREEN_ON);
-        filter.addAction(Intent.ACTION_SCREEN_OFF);
-        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
-        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
-
-        // TODO: Why is this registering the phone as the receiver of the intent
-        //       and not its own handler?
-        p.getContext().registerReceiver(mIntentReceiver, filter, null, p);
-
-
         mDataConnectionTracker = this;
-        mResolver = phone.getContext().getContentResolver();
+        mResolver = mPhone.getContext().getContentResolver();
 
-        apnObserver = new ApnChangeObserver();
+        mApnObserver = new ApnChangeObserver();
         p.getContext().getContentResolver().registerContentObserver(
-                Telephony.Carriers.CONTENT_URI, true, apnObserver);
+                Telephony.Carriers.CONTENT_URI, true, mApnObserver);
 
-        createAllPdpList();
-
-        // This preference tells us 1) initial condition for "dataEnabled",
-        // and 2) whether the RIL will setup the baseband to auto-PS attach.
-        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
-        boolean dataEnabledSetting = true;
-        try {
-            dataEnabledSetting = IConnectivityManager.Stub.asInterface(ServiceManager.
-                getService(Context.CONNECTIVITY_SERVICE)).getMobileDataEnabled();
-        } catch (Exception e) {
-            // nothing to do - use the old behavior and leave data on
-        }
-        dataEnabled[APN_DEFAULT_ID] = !sp.getBoolean(GSMPhone.DATA_DISABLED_ON_BOOT_KEY, false) &&
-                dataEnabledSetting;
-        if (dataEnabled[APN_DEFAULT_ID]) {
-            enabledCount++;
-        }
-        noAutoAttach = !dataEnabled[APN_DEFAULT_ID];
-
-        if (!mRetryMgr.configure(SystemProperties.get("ro.gsm.data_retry_config"))) {
-            if (!mRetryMgr.configure(DEFAULT_DATA_RETRY_CONFIG)) {
-                // Should never happen, log an error and default to a simple linear sequence.
-                Log.e(LOG_TAG, "Could not configure using DEFAULT_DATA_RETRY_CONFIG="
-                        + DEFAULT_DATA_RETRY_CONFIG);
-                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");
-            }
-        }
+        /** Create the default connection */
+        createDataConnection(Phone.APN_TYPE_DEFAULT);
     }
 
+    @Override
     public void dispose() {
+        super.dispose();
+
         //Unregister for all events
-        phone.mCM.unregisterForAvailable(this);
-        phone.mCM.unregisterForOffOrNotAvailable(this);
+        mPhone.mCM.unregisterForAvailable(this);
+        mPhone.mCM.unregisterForOffOrNotAvailable(this);
         mGsmPhone.mSIMRecords.unregisterForRecordsLoaded(this);
-        phone.mCM.unregisterForDataStateChanged(this);
+        mPhone.mCM.unregisterForDataStateChanged(this);
         mGsmPhone.mCT.unregisterForVoiceCallEnded(this);
         mGsmPhone.mCT.unregisterForVoiceCallStarted(this);
         mGsmPhone.mSST.unregisterForGprsAttached(this);
@@ -296,29 +183,36 @@
         mGsmPhone.mSST.unregisterForPsRestrictedEnabled(this);
         mGsmPhone.mSST.unregisterForPsRestrictedDisabled(this);
 
-        phone.getContext().unregisterReceiver(this.mIntentReceiver);
-        phone.getContext().getContentResolver().unregisterContentObserver(this.apnObserver);
+        mPhone.getContext().getContentResolver().unregisterContentObserver(this.mApnObserver);
 
-        destroyAllPdpList();
+        destroyDataConnections();
     }
 
+    @Override
     protected void finalize() {
-        if(DBG) Log.d(LOG_TAG, "GsmDataConnectionTracker finalized");
+        if(DBG) log("finalize");
     }
 
+    @Override
+    protected String getActionIntentReconnectAlarm() {
+        return INTENT_RECONNECT_ALARM;
+    }
+
+    @Override
     protected void setState(State s) {
         if (DBG) log ("setState: " + s);
-        if (state != s) {
-            EventLog.writeEvent(EventLogTags.GSM_DATA_STATE_CHANGE, state.toString(), s.toString());
-            state = s;
+        if (mState != s) {
+            EventLog.writeEvent(EventLogTags.GSM_DATA_STATE_CHANGE, mState.toString(), s.toString());
+            mState = s;
         }
 
-        if (state == State.FAILED) {
-            if (waitingApns != null)
-                waitingApns.clear(); // when teardown the connection and set to IDLE
+        if (mState == State.FAILED) {
+            if (mWaitingApns != null)
+                mWaitingApns.clear(); // when tear down the connection and set to IDLE
         }
     }
 
+    @Override
     public String[] getActiveApnTypes() {
         String[] result;
         if (mActiveApn != null) {
@@ -330,6 +224,7 @@
         return result;
     }
 
+    @Override
     protected String getActiveApnString() {
         String result = null;
         if (mActiveApn != null) {
@@ -347,15 +242,16 @@
      *
      * @return false while no data connection if all above requirements are met.
      */
+    @Override
     public boolean isDataConnectionAsDesired() {
-        boolean roaming = phone.getServiceState().getRoaming();
+        boolean roaming = mPhone.getServiceState().getRoaming();
 
         if (mGsmPhone.mSIMRecords.getRecordsLoaded() &&
                 mGsmPhone.mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE &&
                 (!roaming || getDataOnRoamingEnabled()) &&
             !mIsWifiConnected &&
             !mIsPsRestricted ) {
-            return (state == State.CONNECTED);
+            return (mState == State.CONNECTED);
         }
         return true;
     }
@@ -372,8 +268,8 @@
             return (fetchDunApn() != null);
         }
 
-        if (allApns != null) {
-            for (ApnSetting apn : allApns) {
+        if (mAllApns != null) {
+            for (ApnSetting apn : mAllApns) {
                 if (apn.canHandleType(type)) {
                     return true;
                 }
@@ -382,14 +278,6 @@
         return false;
     }
 
-    /**
-     * Formerly this method was ArrayList<GsmDataConnection> getAllPdps()
-     */
-    public ArrayList<DataConnection> getAllDataConnections() {
-        ArrayList<DataConnection> pdps = (ArrayList<DataConnection>)pdpList.clone();
-        return pdps;
-    }
-
     //****** Called from ServiceStateTracker
     /**
      * Invoked when ServiceStateTracker observes a transition from GPRS
@@ -405,11 +293,11 @@
     }
 
     private void onGprsAttached() {
-        if (state == State.CONNECTED) {
+        if (mState == State.CONNECTED) {
             startNetStatPoll();
             notifyDataConnection(Phone.REASON_GPRS_ATTACHED);
         } else {
-            if (state == State.FAILED) {
+            if (mState == State.FAILED) {
                 cleanUpConnection(false, Phone.REASON_GPRS_ATTACHED);
                 mRetryMgr.resetRetryCount();
             }
@@ -417,26 +305,30 @@
         }
     }
 
+    @Override
     protected boolean isDataAllowed() {
         int gprsState = mGsmPhone.mSST.getCurrentGprsState();
         boolean desiredPowerState = mGsmPhone.mSST.getDesiredPowerState();
 
-        boolean allowed = ((gprsState == ServiceState.STATE_IN_SERVICE || noAutoAttach) &&
-                mGsmPhone.mSIMRecords.getRecordsLoaded() &&
-                phone.getState() == Phone.State.IDLE &&
-                mMasterDataEnabled &&
-                (!phone.getServiceState().getRoaming() || getDataOnRoamingEnabled()) &&
-                !mIsPsRestricted &&
-                desiredPowerState);
+        boolean allowed =
+                    (gprsState == ServiceState.STATE_IN_SERVICE || mAutoAttachOnCreation) &&
+                    mGsmPhone.mSIMRecords.getRecordsLoaded() &&
+                    mPhone.getState() == Phone.State.IDLE &&
+                    mMasterDataEnabled &&
+                    (!mPhone.getServiceState().getRoaming() || getDataOnRoamingEnabled()) &&
+                    !mIsPsRestricted &&
+                    desiredPowerState;
         if (!allowed && DBG) {
             String reason = "";
-            if (gprsState != ServiceState.STATE_IN_SERVICE) reason += " - gprs= " + gprsState;
+            if (!((gprsState == ServiceState.STATE_IN_SERVICE) || mAutoAttachOnCreation)) {
+                reason += " - gprs= " + gprsState;
+            }
             if (!mGsmPhone.mSIMRecords.getRecordsLoaded()) reason += " - SIM not loaded";
-            if (phone.getState() != Phone.State.IDLE) {
-                reason += " - PhoneState= " + phone.getState();
+            if (mPhone.getState() != Phone.State.IDLE) {
+                reason += " - PhoneState= " + mPhone.getState();
             }
             if (!mMasterDataEnabled) reason += " - mMasterDataEnabled= false";
-            if (phone.getServiceState().getRoaming() && getDataOnRoamingEnabled()) {
+            if (mPhone.getServiceState().getRoaming() && getDataOnRoamingEnabled()) {
                 reason += " - Roaming";
             }
             if (mIsPsRestricted) reason += " - mIsPsRestricted= true";
@@ -449,38 +341,38 @@
     private boolean trySetupData(String reason) {
         if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason));
 
-        Log.d(LOG_TAG, "[DSAC DEB] " + "trySetupData with mIsPsRestricted=" + mIsPsRestricted);
+        log("[DSAC DEB] " + "trySetupData with mIsPsRestricted=" + mIsPsRestricted);
 
-        if (phone.getSimulatedRadioControl() != null) {
+        if (mPhone.getSimulatedRadioControl() != null) {
             // Assume data is connected on the simulator
             // FIXME  this can be improved
             setState(State.CONNECTED);
             notifyDataConnection(reason);
 
-            Log.i(LOG_TAG, "(fix?) We're on the simulator; assuming data is connected");
+            log("(fix?) We're on the simulator; assuming data is connected");
             return true;
         }
 
         int gprsState = mGsmPhone.mSST.getCurrentGprsState();
         boolean desiredPowerState = mGsmPhone.mSST.getDesiredPowerState();
 
-        if (((state == State.IDLE) || (state == State.SCANNING)) &&
+        if (((mState == State.IDLE) || (mState == State.SCANNING)) &&
                 isDataAllowed() && getAnyDataEnabled()) {
 
-            if (state == State.IDLE) {
-                waitingApns = buildWaitingApns();
-                if (waitingApns.isEmpty()) {
+            if (mState == State.IDLE) {
+                mWaitingApns = buildWaitingApns(mRequestedApnType);
+                if (mWaitingApns.isEmpty()) {
                     if (DBG) log("No APN found");
                     notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN);
                     notifyOffApnsOfAvailability(reason, false);
                     return false;
                 } else {
-                    log ("Create from allApns : " + apnListToString(allApns));
+                    log ("Create from allApns : " + apnListToString(mAllApns));
                 }
             }
 
             if (DBG) {
-                log ("Setup waitngApns : " + apnListToString(waitingApns));
+                log ("Setup waitngApns : " + apnListToString(mWaitingApns));
             }
             boolean retValue = setupData(reason);
             notifyOffApnsOfAvailability(reason, retValue);
@@ -492,13 +384,12 @@
     }
 
     /**
-     * If tearDown is true, this only tears down a CONNECTED session. Presently,
-     * there is no mechanism for abandoning an INITING/CONNECTING session,
-     * but would likely involve cancelling pending async requests or
-     * setting a flag or new state to ignore them when they came in
-     * @param tearDown true if the underlying GsmDataConnection should be
-     * disconnected.
-     * @param reason reason for the clean up.
+     * Cleanup all connections.
+     *
+     * TODO: Cleanup only a specified connection passed as a parameter.
+     *
+     * @param tearDown true if the underlying DataConnection should be disconnected.
+     * @param reason for the clean up.
      */
     private void cleanUpConnection(boolean tearDown, String reason) {
         if (DBG) log("Clean up connection due to " + reason);
@@ -506,7 +397,7 @@
         // Clear the reconnect alarm, if set.
         if (mReconnectIntent != null) {
             AlarmManager am =
-                (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
+                (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
             am.cancel(mReconnectIntent);
             mReconnectIntent = null;
         }
@@ -514,10 +405,11 @@
         setState(State.DISCONNECTING);
 
         boolean notificationDeferred = false;
-        for (DataConnection conn : pdpList) {
+        for (DataConnection conn : mDataConnections.values()) {
             if (tearDown) {
                 if (DBG) log("cleanUpConnection: teardown, call conn.disconnect");
-                conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE, reason));
+                conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE,
+                        conn.getDataConnectionId(), 0, reason));
                 notificationDeferred = true;
             } else {
                 if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously");
@@ -575,51 +467,49 @@
         return result;
     }
 
-    private GsmDataConnection findFreePdp() {
-        for (DataConnection conn : pdpList) {
-            GsmDataConnection pdp = (GsmDataConnection) conn;
-            if (pdp.isInactive()) {
-                return pdp;
+    private GsmDataConnection findFreeDataConnection() {
+        for (DataConnection dc : mDataConnections.values()) {
+            if (dc.isInactive()) {
+                log("found free GsmDataConnection");
+                return (GsmDataConnection) dc;
             }
         }
+        log("NO free GsmDataConnection");
         return null;
     }
 
     private boolean setupData(String reason) {
         ApnSetting apn;
-        GsmDataConnection pdp;
+        GsmDataConnection gdc;
 
         apn = getNextApn();
         if (apn == null) return false;
-        pdp = findFreePdp();
-        if (pdp == null) {
+        gdc = findFreeDataConnection();
+        if (gdc == null) {
             if (DBG) log("setupData: No free GsmDataConnection found!");
             return false;
         }
         mActiveApn = apn;
-        mActivePdp = pdp;
+        mPendingDataConnection = gdc;
 
         Message msg = obtainMessage();
         msg.what = EVENT_DATA_SETUP_COMPLETE;
         msg.obj = reason;
-        pdp.connect(msg, apn);
+        gdc.connect(msg, apn);
 
         setState(State.INITING);
         notifyDataConnection(reason);
         return true;
     }
 
-    private boolean
-    pdpStatesHasCID (ArrayList<DataCallState> states, int cid) {
+    private boolean dataCallStatesHasCID (ArrayList<DataCallState> states, int cid) {
         for (int i = 0, s = states.size() ; i < s ; i++) {
             if (states.get(i).cid == cid) return true;
         }
-
         return false;
     }
 
-    private boolean
-    pdpStatesHasActiveCID (ArrayList<DataCallState> states, int cid) {
+    private boolean dataCallStatesHasActiveCID (ArrayList<DataCallState> states, int cid) {
         for (int i = 0, s = states.size() ; i < s ; i++) {
             if ((states.get(i).cid == cid) && (states.get(i).active != 0)) {
                 return true;
@@ -635,7 +525,7 @@
     private void onApnChanged() {
         boolean isConnected;
 
-        isConnected = (state != State.IDLE && state != State.FAILED);
+        isConnected = (mState != State.IDLE && mState != State.FAILED);
 
         // The "current" may no longer be valid.  MMS depends on this to send properly.
         mGsmPhone.updateCurrentCarrierInProvider();
@@ -643,7 +533,7 @@
         // TODO: It'd be nice to only do this if the changed entrie(s)
         // match the current operator.
         createAllApnList();
-        if (state != State.DISCONNECTING) {
+        if (mState != State.DISCONNECTING) {
             cleanUpConnection(isConnected, Phone.REASON_APN_CHANGED);
             if (!isConnected) {
                 // reset reconnect timer
@@ -660,10 +550,10 @@
      * via an unsolicited response (which could have happened at any
      * previous state
      */
-    protected void onPdpStateChanged (AsyncResult ar, boolean explicitPoll) {
-        ArrayList<DataCallState> pdpStates;
+    private void onDataStateChanged (AsyncResult ar, boolean explicitPoll) {
+        ArrayList<DataCallState> dataCallStates;
 
-        pdpStates = (ArrayList<DataCallState>)(ar.result);
+        dataCallStates = (ArrayList<DataCallState>)(ar.result);
 
         if (ar.exception != null) {
             // This is probably "radio not available" or something
@@ -672,42 +562,42 @@
             return;
         }
 
-        if (state == State.CONNECTED) {
+        if (mState == State.CONNECTED) {
             // The way things are supposed to work, the PDP list
             // should not contain the CID after it disconnects.
             // However, the way things really work, sometimes the PDP
             // context is still listed with active = false, which
             // makes it hard to distinguish an activating context from
             // an activated-and-then deactivated one.
-            if (!pdpStatesHasCID(pdpStates, cidActive)) {
+            if (!dataCallStatesHasCID(dataCallStates, mCidActive)) {
                 // It looks like the PDP context has deactivated.
                 // Tear everything down and try to reconnect.
 
-                Log.i(LOG_TAG, "PDP connection has dropped. Reconnecting");
+                log("PDP connection has dropped. Reconnecting");
 
                 // Add an event log when the network drops PDP
-                GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
+                GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation());
                 EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP,
                         loc != null ? loc.getCid() : -1,
                         TelephonyManager.getDefault().getNetworkType());
 
                 cleanUpConnection(true, null);
                 return;
-            } else if (!pdpStatesHasActiveCID(pdpStates, cidActive)) {
+            } else if (!dataCallStatesHasActiveCID(dataCallStates, mCidActive)) {
                 // Here, we only consider this authoritative if we asked for the
                 // PDP list. If it was an unsolicited response, we poll again
                 // to make sure everyone agrees on the initial state.
 
                 if (!explicitPoll) {
                     // We think it disconnected but aren't sure...poll from our side
-                    phone.mCM.getPDPContextList(
+                    mPhone.mCM.getPDPContextList(
                             this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
                 } else {
-                    Log.i(LOG_TAG, "PDP connection has dropped (active=false case). "
+                    log("PDP connection has dropped (active=false case). "
                                     + " Reconnecting");
 
                     // Log the network drop on the event log.
-                    GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
+                    GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation());
                     EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP,
                             loc != null ? loc.getCid() : -1,
                             TelephonyManager.getDefault().getNetworkType());
@@ -734,38 +624,26 @@
         mActiveApn = null;
     }
 
-    /**
-     * This is a kludge to deal with the fact that
-     * the PDP state change notification doesn't always work
-     * with certain RIL impl's/basebands
-     *
-     */
-    private void startPeriodicPdpPoll() {
-        removeMessages(EVENT_POLL_PDP);
-
-        sendMessageDelayed(obtainMessage(EVENT_POLL_PDP), POLL_PDP_MILLIS);
-    }
-
     private void resetPollStats() {
-        txPkts = -1;
-        rxPkts = -1;
-        sentSinceLastRecv = 0;
-        netStatPollPeriod = POLL_NETSTAT_MILLIS;
+        mTxPkts = -1;
+        mRxPkts = -1;
+        mSentSinceLastRecv = 0;
+        mNetStatPollPeriod = POLL_NETSTAT_MILLIS;
         mNoRecvPollCount = 0;
     }
 
     private void doRecovery() {
-        if (state == State.CONNECTED) {
+        if (mState == State.CONNECTED) {
             int maxPdpReset = Settings.Secure.getInt(mResolver,
                     Settings.Secure.PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT,
                     DEFAULT_MAX_PDP_RESET_FAIL);
             if (mPdpResetCount < maxPdpReset) {
                 mPdpResetCount++;
-                EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, sentSinceLastRecv);
+                EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, mSentSinceLastRecv);
                 cleanUpConnection(true, Phone.REASON_PDP_RESET);
             } else {
                 mPdpResetCount = 0;
-                EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, sentSinceLastRecv);
+                EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, mSentSinceLastRecv);
                 mGsmPhone.mSST.reRegisterNetwork(null);
             }
             // TODO: Add increasingly drastic recovery steps, eg,
@@ -773,23 +651,26 @@
         }
     }
 
+    @Override
     protected void startNetStatPoll() {
-        if (state == State.CONNECTED && mPingTestActive == false && netStatPollEnabled == false) {
-            Log.d(LOG_TAG, "[DataConnection] Start poll NetStat");
+        if (mState == State.CONNECTED && mPingTestActive == false && mNetStatPollEnabled == false) {
+            log("[DataConnection] Start poll NetStat");
             resetPollStats();
-            netStatPollEnabled = true;
+            mNetStatPollEnabled = true;
             mPollNetStat.run();
         }
     }
 
+    @Override
     protected void stopNetStatPoll() {
-        netStatPollEnabled = false;
+        mNetStatPollEnabled = false;
         removeCallbacks(mPollNetStat);
-        Log.d(LOG_TAG, "[DataConnection] Stop poll NetStat");
+        log("[DataConnection] Stop poll NetStat");
     }
 
+    @Override
     protected void restartRadio() {
-        Log.d(LOG_TAG, "************TURN OFF RADIO**************");
+        log("************TURN OFF RADIO**************");
         cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
         mGsmPhone.mSST.powerOffRadioSafely();
         /* Note: no need to call setRadioPower(true).  Assuming the desired
@@ -813,43 +694,43 @@
 
             Activity newActivity;
 
-            preTxPkts = txPkts;
-            preRxPkts = rxPkts;
+            preTxPkts = mTxPkts;
+            preRxPkts = mRxPkts;
 
-            txPkts = TrafficStats.getMobileTxPackets();
-            rxPkts = TrafficStats.getMobileRxPackets();
+            mTxPkts = TrafficStats.getMobileTxPackets();
+            mRxPkts = TrafficStats.getMobileRxPackets();
 
-            //Log.d(LOG_TAG, "rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts));
+            //log("rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts));
 
-            if (netStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) {
-                sent = txPkts - preTxPkts;
-                received = rxPkts - preRxPkts;
+            if (mNetStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) {
+                sent = mTxPkts - preTxPkts;
+                received = mRxPkts - preRxPkts;
 
                 if ( sent > 0 && received > 0 ) {
-                    sentSinceLastRecv = 0;
+                    mSentSinceLastRecv = 0;
                     newActivity = Activity.DATAINANDOUT;
                     mPdpResetCount = 0;
                 } else if (sent > 0 && received == 0) {
-                    if (phone.getState() == Phone.State.IDLE) {
-                        sentSinceLastRecv += sent;
+                    if (mPhone.getState() == Phone.State.IDLE) {
+                        mSentSinceLastRecv += sent;
                     } else {
-                        sentSinceLastRecv = 0;
+                        mSentSinceLastRecv = 0;
                     }
                     newActivity = Activity.DATAOUT;
                 } else if (sent == 0 && received > 0) {
-                    sentSinceLastRecv = 0;
+                    mSentSinceLastRecv = 0;
                     newActivity = Activity.DATAIN;
                     mPdpResetCount = 0;
                 } else if (sent == 0 && received == 0) {
                     newActivity = Activity.NONE;
                 } else {
-                    sentSinceLastRecv = 0;
+                    mSentSinceLastRecv = 0;
                     newActivity = Activity.NONE;
                 }
 
-                if (activity != newActivity && mIsScreenOn) {
-                    activity = newActivity;
-                    phone.notifyDataActivity();
+                if (mActivity != newActivity && mIsScreenOn) {
+                    mActivity = newActivity;
+                    mPhone.notifyDataActivity();
                 }
             }
 
@@ -857,11 +738,11 @@
                     Settings.Secure.PDP_WATCHDOG_TRIGGER_PACKET_COUNT,
                     NUMBER_SENT_PACKETS_OF_HANG);
 
-            if (sentSinceLastRecv >= watchdogTrigger) {
+            if (mSentSinceLastRecv >= watchdogTrigger) {
                 // we already have NUMBER_SENT_PACKETS sent without ack
                 if (mNoRecvPollCount == 0) {
                     EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET_COUNTDOWN_TRIGGERED,
-                            sentSinceLastRecv);
+                            mSentSinceLastRecv);
                 }
 
                 int noRecvPollLimit = Settings.Secure.getInt(mResolver,
@@ -871,21 +752,22 @@
                     // It's possible the PDP context went down and we weren't notified.
                     // Start polling the context list in an attempt to recover.
                     if (DBG) log("no DATAIN in a while; polling PDP");
-                    phone.mCM.getDataCallList(obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
+                    mPhone.mCM.getDataCallList(obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
 
                     mNoRecvPollCount++;
 
                     // Slow down the poll interval to let things happen
-                    netStatPollPeriod = Settings.Secure.getInt(mResolver,
+                    mNetStatPollPeriod = Settings.Secure.getInt(mResolver,
                             Settings.Secure.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS,
                             POLL_NETSTAT_SLOW_MILLIS);
                 } else {
-                    if (DBG) log("Sent " + String.valueOf(sentSinceLastRecv) +
+                    if (DBG) log("Sent " + String.valueOf(mSentSinceLastRecv) +
                                         " pkts since last received");
                     // We've exceeded the threshold.  Run ping test as a final check;
                     // it will proceed with recovery if ping fails.
                     stopNetStatPoll();
                     Thread pingTest = new Thread() {
+                        @Override
                         public void run() {
                             runPingTest();
                         }
@@ -896,17 +778,17 @@
             } else {
                 mNoRecvPollCount = 0;
                 if (mIsScreenOn) {
-                    netStatPollPeriod = Settings.Secure.getInt(mResolver,
+                    mNetStatPollPeriod = Settings.Secure.getInt(mResolver,
                             Settings.Secure.PDP_WATCHDOG_POLL_INTERVAL_MS, POLL_NETSTAT_MILLIS);
                 } else {
-                    netStatPollPeriod = Settings.Secure.getInt(mResolver,
+                    mNetStatPollPeriod = Settings.Secure.getInt(mResolver,
                             Settings.Secure.PDP_WATCHDOG_LONG_POLL_INTERVAL_MS,
                             POLL_NETSTAT_SCREEN_OFF_MILLIS);
                 }
             }
 
-            if (netStatPollEnabled) {
-                mDataConnectionTracker.postDelayed(this, netStatPollPeriod);
+            if (mNetStatPollEnabled) {
+                mDataConnectionTracker.postDelayed(this, mNetStatPollPeriod);
             }
         }
     };
@@ -925,9 +807,9 @@
                 status = p.waitFor();
             }
         } catch (IOException e) {
-            Log.w(LOG_TAG, "ping failed: IOException");
+            loge("ping failed: IOException");
         } catch (Exception e) {
-            Log.w(LOG_TAG, "exception trying to ping");
+            loge("exception trying to ping");
         }
 
         if (status == 0) {
@@ -968,7 +850,8 @@
     }
 
     private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
-        if (state == State.FAILED) {
+        if (mState == State.FAILED) {
+            /** TODO: Retrieve retry manager from connection itself */
             if (!mRetryMgr.isRetryNeeded()) {
                 if (!mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
                     // if no more retries on a secondary APN attempt, tell the world and revert.
@@ -977,11 +860,11 @@
                     return;
                 }
                 if (mReregisterOnReconnectFailure) {
-                    // We've re-registerd once now just retry forever.
+                    // We've re-registered once now just retry forever.
                     mRetryMgr.retryForeverUsingLastTimeout();
                 } else {
                     // Try to re-register to the network.
-                    Log.d(LOG_TAG, "PDP activate failed, Reregistering to the network");
+                    log("PDP activate failed, Reregistering to the network");
                     mReregisterOnReconnectFailure = true;
                     mGsmPhone.mSST.reRegisterNetwork(null);
                     mRetryMgr.resetRetryCount();
@@ -990,15 +873,15 @@
             }
 
             int nextReconnectDelay = mRetryMgr.getRetryTimer();
-            Log.d(LOG_TAG, "PDP activate failed. Scheduling next attempt for "
+            log("PDP activate failed. Scheduling next attempt for "
                     + (nextReconnectDelay / 1000) + "s");
 
             AlarmManager am =
-                (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
+                (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
             Intent intent = new Intent(INTENT_RECONNECT_ALARM);
             intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, reason);
             mReconnectIntent = PendingIntent.getBroadcast(
-                    phone.getContext(), 0, intent, 0);
+                    mPhone.getContext(), 0, intent, 0);
             am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                     SystemClock.elapsedRealtime() + nextReconnectDelay,
                     mReconnectIntent);
@@ -1006,7 +889,7 @@
             mRetryMgr.increaseRetryCount();
 
             if (!shouldPostNotification(lastFailCauseCode)) {
-                Log.d(LOG_TAG,"NOT Posting GPRS Unavailable notification "
+                log("NOT Posting GPRS Unavailable notification "
                                 + "-- likely transient error");
             } else {
                 notifyNoData(lastFailCauseCode);
@@ -1018,9 +901,9 @@
         setState(State.FAILED);
     }
 
-    protected void onRecordsLoaded() {
+    private void onRecordsLoaded() {
         createAllApnList();
-        if (state == State.FAILED) {
+        if (mState == State.FAILED) {
             cleanUpConnection(false, null);
         }
         sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, Phone.REASON_SIM_LOADED));
@@ -1028,19 +911,29 @@
 
     @Override
     protected void onEnableNewApn() {
+        log("onEnableNewApn E");
         // change our retry manager to use the appropriate numbers for the new APN
         if (mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
-            mRetryMgr = mDefaultRetryManager;
+            log("onEnableNewApn default type");
+            mRetryMgr = mPendingDataConnection.getRetryMgr();
+            mRetryMgr.resetRetryCount();
+        } else if (mApnToDataConnectionId.get(mRequestedApnType) == null) {
+            log("onEnableNewApn mRequestedApnType=" + mRequestedApnType +
+                    " missing, make a new connection");
+            int id = createDataConnection(mRequestedApnType);
+            mRetryMgr = mDataConnections.get(id).getRetryMgr();
+            mRetryMgr.resetRetryCount();
         } else {
-            mRetryMgr = mSecondaryRetryManager;
+            log("oneEnableNewApn connection already exists, nothing to setup");
         }
-        mRetryMgr.resetRetryCount();
 
         // TODO:  To support simultaneous PDP contexts, this should really only call
         // cleanUpConnection if it needs to free up a GsmDataConnection.
         cleanUpConnection(true, Phone.REASON_APN_SWITCHED);
+        log("onEnableNewApn X");
     }
 
+    @Override
     protected boolean onTrySetupData(String reason) {
         return trySetupData(reason);
     }
@@ -1060,31 +953,33 @@
         }
     }
 
+    @Override
     protected void onRadioAvailable() {
-        if (phone.getSimulatedRadioControl() != null) {
+        if (mPhone.getSimulatedRadioControl() != null) {
             // Assume data is connected on the simulator
             // FIXME  this can be improved
             setState(State.CONNECTED);
             notifyDataConnection(null);
 
-            Log.i(LOG_TAG, "We're on the simulator; assuming data is connected");
+            log("We're on the simulator; assuming data is connected");
         }
 
-        if (state != State.IDLE) {
+        if (mState != State.IDLE) {
             cleanUpConnection(true, null);
         }
     }
 
+    @Override
     protected void onRadioOffOrNotAvailable() {
         // Make sure our reconnect delay starts at the initial value
         // next time the radio comes on
         mRetryMgr.resetRetryCount();
         mReregisterOnReconnectFailure = false;
 
-        if (phone.getSimulatedRadioControl() != null) {
+        if (mPhone.getSimulatedRadioControl() != null) {
             // Assume data is connected on the simulator
             // FIXME  this can be improved
-            Log.i(LOG_TAG, "We're on the simulator; assuming radio off is meaningless");
+            log("We're on the simulator; assuming radio off is meaningless");
         } else {
             if (DBG) log("Radio is off and clean up all connection");
             // TODO: Should we reset mRequestedApnType to "default"?
@@ -1092,7 +987,9 @@
         }
     }
 
+    @Override
     protected void onDataSetupComplete(AsyncResult ar) {
+        /** TODO: Which connection is completing should be a parameter */
         String reason = null;
         if (ar.userObj instanceof String) {
             reason = (String) ar.userObj;
@@ -1100,10 +997,10 @@
 
         if (ar.exception == null) {
             // TODO: We should clear LinkProperties/Capabilities when torn down or disconnected
-            mLinkProperties = getLinkProperties(mActivePdp);
-            mLinkCapabilities = getLinkCapabilities(mActivePdp);
+            mLinkProperties = getLinkProperties(mPendingDataConnection);
+            mLinkCapabilities = getLinkCapabilities(mPendingDataConnection);
 
-            ApnSetting apn = mActivePdp.getApn();
+            ApnSetting apn = mPendingDataConnection.getApn();
             if (apn.proxy != null && apn.proxy.length() != 0) {
                 try {
                     ProxyProperties proxy = new ProxyProperties();
@@ -1111,11 +1008,11 @@
                             Integer.parseInt(apn.port)));
                     mLinkProperties.setHttpProxy(proxy);
                 } catch (UnknownHostException e) {
-                    Log.e(LOG_TAG, "UnknownHostException making ProxyProperties: " + e);
+                    loge("UnknownHostException making ProxyProperties: " + e);
                 } catch (SecurityException e) {
-                    Log.e(LOG_TAG, "SecurityException making ProxyProperties: " + e);
+                    loge("SecurityException making ProxyProperties: " + e);
                 } catch (NumberFormatException e) {
-                    Log.e(LOG_TAG, "NumberFormatException making ProxyProperties (" + apn.port +
+                    loge("NumberFormatException making ProxyProperties (" + apn.port +
                             "): " + e);
                 }
             }
@@ -1123,10 +1020,10 @@
             // everything is setup
             if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
                 SystemProperties.set("gsm.defaultpdpcontext.active", "true");
-                        if (canSetPreferApn && preferredApn == null) {
-                            Log.d(LOG_TAG, "PREFERRED APN is null");
-                            preferredApn = mActiveApn;
-                            setPreferredApn(preferredApn.id);
+                        if (canSetPreferApn && mPreferredApn == null) {
+                            log("PREFERRED APN is null");
+                            mPreferredApn = mActiveApn;
+                            setPreferredApn(mPreferredApn.id);
                         }
             } else {
                 SystemProperties.set("gsm.defaultpdpcontext.active", "false");
@@ -1143,13 +1040,14 @@
             if(DBG) log("PDP setup failed " + cause);
                     // Log this failure to the Event Logs.
             if (cause.isEventLoggable()) {
-                GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
+                GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation());
                 EventLog.writeEvent(EventLogTags.PDP_SETUP_FAIL,
                         cause.ordinal(), loc != null ? loc.getCid() : -1,
                         TelephonyManager.getDefault().getNetworkType());
             }
 
-            // No try for permanent failure
+            // Do not retry on permanent failure
+            // TODO: We should not fail permanently if more Apns to try!
             if (cause.isPermanentFail()) {
                 notifyNoData(cause);
                 notifyDataConnection(Phone.REASON_APN_FAILED);
@@ -1157,8 +1055,8 @@
                 return;
             }
 
-            waitingApns.remove(0);
-            if (waitingApns.isEmpty()) {
+            mWaitingApns.remove(0);
+            if (mWaitingApns.isEmpty()) {
                 // No more to try, start delayed retry
                 startDelayedRetry(cause, reason);
             } else {
@@ -1174,9 +1072,10 @@
     /**
      * Called when EVENT_DISCONNECT_DONE is received.
      */
-    protected void onDisconnectDone(AsyncResult ar) {
+    @Override
+    protected void onDisconnectDone(int connId, AsyncResult ar) {
+        if(DBG) log("EVENT_DISCONNECT_DONE connId=" + connId);
         String reason = null;
-        if(DBG) log("EVENT_DISCONNECT_DONE");
         if (ar.userObj instanceof String) {
            reason = (String) ar.userObj;
         }
@@ -1202,22 +1101,24 @@
     }
 
     protected void onPollPdp() {
-        if (state == State.CONNECTED) {
+        if (mState == State.CONNECTED) {
             // only poll when connected
-            phone.mCM.getPDPContextList(this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
+            mPhone.mCM.getPDPContextList(this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
             sendMessageDelayed(obtainMessage(EVENT_POLL_PDP), POLL_PDP_MILLIS);
         }
     }
 
+    @Override
     protected void onVoiceCallStarted() {
-        if (state == State.CONNECTED && ! mGsmPhone.mSST.isConcurrentVoiceAndData()) {
+        if (mState == State.CONNECTED && ! mGsmPhone.mSST.isConcurrentVoiceAndData()) {
             stopNetStatPoll();
             notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
         }
     }
 
+    @Override
     protected void onVoiceCallEnded() {
-        if (state == State.CONNECTED) {
+        if (mState == State.CONNECTED) {
             if (!mGsmPhone.mSST.isConcurrentVoiceAndData()) {
                 startNetStatPoll();
                 notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
@@ -1234,74 +1135,92 @@
         }
     }
 
+    @Override
     protected void onCleanUpConnection(boolean tearDown, String reason) {
         cleanUpConnection(tearDown, reason);
     }
 
     /**
-     * Based on the sim operator numeric, create a list for all possible pdps
-     * with all apns associated with that pdp
-     *
-     *
+     * Based on the sim operator numeric, create a list for all possible
+     * Data Connections and setup the preferredApn.
      */
     private void createAllApnList() {
-        allApns = new ArrayList<ApnSetting>();
+        mAllApns = new ArrayList<ApnSetting>();
         String operator = mGsmPhone.mSIMRecords.getSIMOperatorNumeric();
 
         if (operator != null) {
             String selection = "numeric = '" + operator + "'";
 
-            Cursor cursor = phone.getContext().getContentResolver().query(
+            Cursor cursor = mPhone.getContext().getContentResolver().query(
                     Telephony.Carriers.CONTENT_URI, null, selection, null, null);
 
             if (cursor != null) {
                 if (cursor.getCount() > 0) {
-                    allApns = createApnList(cursor);
-                    // TODO: Figure out where this fits in.  This basically just
-                    // writes the pap-secrets file.  No longer tied to GsmDataConnection
-                    // object.  Not used on current platform (no ppp).
-                    //GsmDataConnection pdp = pdpList.get(pdp_name);
-                    //if (pdp != null && pdp.dataLink != null) {
-                    //    pdp.dataLink.setPasswordInfo(cursor);
-                    //}
+                    mAllApns = createApnList(cursor);
                 }
                 cursor.close();
             }
         }
 
-        if (allApns.isEmpty()) {
+        if (mAllApns.isEmpty()) {
             if (DBG) log("No APN found for carrier: " + operator);
-            preferredApn = null;
+            mPreferredApn = null;
             notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN);
         } else {
-            preferredApn = getPreferredApn();
-            Log.d(LOG_TAG, "Get PreferredAPN");
-            if (preferredApn != null && !preferredApn.numeric.equals(operator)) {
-                preferredApn = null;
+            mPreferredApn = getPreferredApn();
+            log("Get PreferredAPN");
+            if (mPreferredApn != null && !mPreferredApn.numeric.equals(operator)) {
+                mPreferredApn = null;
                 setPreferredApn(-1);
             }
         }
     }
 
-    private void createAllPdpList() {
-        pdpList = new ArrayList<DataConnection>();
-        DataConnection pdp;
+    /** Return the id for a new data connection */
+    private int createDataConnection(String apnType) {
+        log("createDataConnection(" + apnType + ") E");
+        RetryManager rm = new RetryManager();
 
-        for (int i = 0; i < PDP_CONNECTION_POOL_SIZE; i++) {
-            pdp = GsmDataConnection.makeDataConnection(mGsmPhone);
-            pdpList.add(pdp);
-         }
+        if (apnType.equals(Phone.APN_TYPE_DEFAULT)) {
+            if (!rm.configure(SystemProperties.get("ro.gsm.data_retry_config"))) {
+                if (!rm.configure(DEFAULT_DATA_RETRY_CONFIG)) {
+                    // Should never happen, log an error and default to a simple linear sequence.
+                    log("Could not configure using DEFAULT_DATA_RETRY_CONFIG="
+                            + DEFAULT_DATA_RETRY_CONFIG);
+                    rm.configure(20, 2000, 1000);
+                }
+            }
+        } else {
+            if (!rm.configure(SystemProperties.get("ro.gsm.2nd_data_retry_config"))) {
+                if (!rm.configure(SECONDARY_DATA_RETRY_CONFIG)) {
+                    // Should never happen, log an error and default to a simple sequence.
+                    log("Could note configure using SECONDARY_DATA_RETRY_CONFIG="
+                            + SECONDARY_DATA_RETRY_CONFIG);
+                    rm.configure("max_retries=3, 333, 333, 333");
+                }
+            }
+        }
+
+        int id = mUniqueIdGenerator.getAndIncrement();
+        DataConnection conn = GsmDataConnection.makeDataConnection(mGsmPhone, id, rm);
+        mDataConnections.put(id, conn);
+        mApnToDataConnectionId.put(apnType, id);
+
+        log("createDataConnection(" + apnType + ") X id=" + id);
+        return id;
     }
 
-    private void destroyAllPdpList() {
-        if(pdpList != null) {
-            GsmDataConnection pdp;
-            pdpList.removeAll(pdpList);
+    private void destroyDataConnections() {
+        if(mDataConnections != null) {
+            log("destroyDataConnectionList clear mDataConnectionList");
+            mDataConnections.clear();
+        } else {
+            log("destroyDataConnectionList mDataConnecitonList is empty, ignore");
         }
     }
 
     private ApnSetting fetchDunApn() {
-        Context c = phone.getContext();
+        Context c = mPhone.getContext();
         String apnData = Settings.Secure.getString(c.getContentResolver(),
                                     Settings.Secure.TETHER_DUN_APN);
         ApnSetting dunSetting = ApnSetting.fromString(apnData);
@@ -1312,14 +1231,16 @@
     }
 
     /**
+     * Build a list of APNs to be used to create PDP's.
      *
+     * @param requestedApnType
      * @return waitingApns list to be used to create PDP
      *          error when waitingApns.isEmpty()
      */
-    private ArrayList<ApnSetting> buildWaitingApns() {
+    private ArrayList<ApnSetting> buildWaitingApns(String requestedApnType) {
         ArrayList<ApnSetting> apnList = new ArrayList<ApnSetting>();
 
-        if (mRequestedApnType.equals(Phone.APN_TYPE_DUN)) {
+        if (requestedApnType.equals(Phone.APN_TYPE_DUN)) {
             ApnSetting dun = fetchDunApn();
             if (dun != null) apnList.add(dun);
             return apnList;
@@ -1327,24 +1248,24 @@
 
         String operator = mGsmPhone.mSIMRecords.getSIMOperatorNumeric();
 
-        if (mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
-            if (canSetPreferApn && preferredApn != null) {
-                Log.i(LOG_TAG, "Preferred APN:" + operator + ":"
-                        + preferredApn.numeric + ":" + preferredApn);
-                if (preferredApn.numeric.equals(operator)) {
-                    Log.i(LOG_TAG, "Waiting APN set to preferred APN");
-                    apnList.add(preferredApn);
+        if (requestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
+            if (canSetPreferApn && mPreferredApn != null) {
+                log("Preferred APN:" + operator + ":"
+                        + mPreferredApn.numeric + ":" + mPreferredApn);
+                if (mPreferredApn.numeric.equals(operator)) {
+                    log("Waiting APN set to preferred APN");
+                    apnList.add(mPreferredApn);
                     return apnList;
                 } else {
                     setPreferredApn(-1);
-                    preferredApn = null;
+                    mPreferredApn = null;
                 }
             }
         }
 
-        if (allApns != null) {
-            for (ApnSetting apn : allApns) {
-                if (apn.canHandleType(mRequestedApnType)) {
+        if (mAllApns != null) {
+            for (ApnSetting apn : mAllApns) {
+                if (apn.canHandleType(requestedApnType)) {
                     apnList.add(apn);
                 }
             }
@@ -1357,7 +1278,7 @@
      * @return the first apn found in waitingApns, null if none
      */
     private ApnSetting getNextApn() {
-        ArrayList<ApnSetting> list = waitingApns;
+        ArrayList<ApnSetting> list = mWaitingApns;
         ApnSetting apn = null;
 
         if (list != null) {
@@ -1388,7 +1309,7 @@
             return;
         }
 
-        ContentResolver resolver = phone.getContext().getContentResolver();
+        ContentResolver resolver = mPhone.getContext().getContentResolver();
         resolver.delete(PREFERAPN_URI, null, null);
 
         if (pos >= 0) {
@@ -1399,11 +1320,11 @@
     }
 
     private ApnSetting getPreferredApn() {
-        if (allApns.isEmpty()) {
+        if (mAllApns.isEmpty()) {
             return null;
         }
 
-        Cursor cursor = phone.getContext().getContentResolver().query(
+        Cursor cursor = mPhone.getContext().getContentResolver().query(
                 PREFERAPN_URI, new String[] { "_id", "name", "apn" },
                 null, null, Telephony.Carriers.DEFAULT_SORT_ORDER);
 
@@ -1417,7 +1338,7 @@
             int pos;
             cursor.moveToFirst();
             pos = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID));
-            for(ApnSetting p:allApns) {
+            for(ApnSetting p:mAllApns) {
                 if (p.id == pos && p.canHandleType(mRequestedApnType)) {
                     cursor.close();
                     return p;
@@ -1432,11 +1353,12 @@
         return null;
     }
 
+    @Override
     public void handleMessage (Message msg) {
-        if (DBG) Log.d(LOG_TAG,"GSMDataConnTrack handleMessage "+msg);
+        if (DBG) log("GSMDataConnTrack handleMessage "+msg);
 
         if (!mGsmPhone.mIsTheCurrentActivePhone) {
-            Log.d(LOG_TAG, "Ignore GSM msgs since GSM phone is inactive");
+            log("Ignore GSM msgs since GSM phone is inactive");
             return;
         }
 
@@ -1454,11 +1376,11 @@
                 break;
 
             case EVENT_DATA_STATE_CHANGED:
-                onPdpStateChanged((AsyncResult) msg.obj, false);
+                onDataStateChanged((AsyncResult) msg.obj, false);
                 break;
 
             case EVENT_GET_PDP_LIST_COMPLETE:
-                onPdpStateChanged((AsyncResult) msg.obj, true);
+                onDataStateChanged((AsyncResult) msg.obj, true);
                 break;
 
             case EVENT_POLL_PDP:
@@ -1486,7 +1408,7 @@
                  * PDP context and notify us with PDP_CONTEXT_CHANGED.
                  * But we should stop the network polling and prevent reset PDP.
                  */
-                Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted);
+                log("[DSAC DEB] " + "EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted);
                 stopNetStatPoll();
                 mIsPsRestricted = true;
                 break;
@@ -1496,12 +1418,12 @@
                  * When PS restrict is removed, we need setup PDP connection if
                  * PDP connection is down.
                  */
-                Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
+                log("[DSAC DEB] " + "EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
                 mIsPsRestricted  = false;
-                if (state == State.CONNECTED) {
+                if (mState == State.CONNECTED) {
                     startNetStatPoll();
                 } else {
-                    if (state == State.FAILED) {
+                    if (mState == State.FAILED) {
                         cleanUpConnection(false, Phone.REASON_PS_RESTRICT_ENABLED);
                         mRetryMgr.resetRetryCount();
                         mReregisterOnReconnectFailure = false;
@@ -1517,7 +1439,13 @@
         }
     }
 
+    @Override
     protected void log(String s) {
         Log.d(LOG_TAG, "[GsmDataConnectionTracker] " + s);
     }
+
+    @Override
+    protected void loge(String s) {
+        Log.e(LOG_TAG, "[GsmDataConnectionTracker] " + s);
+    }
 }