/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.telephony.gsm;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
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.NetworkInfo;
import android.net.wifi.WifiManager;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.INetStatService;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.preference.PreferenceManager;
import android.provider.Checkin;
import android.provider.Settings;
import android.provider.Telephony;
import android.provider.Settings.SettingNotFoundException;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;

import com.android.internal.telephony.Phone;
import com.android.internal.telephony.gsm.PdpConnection.PdpFailCause;

import java.io.IOException;
import java.util.ArrayList;

/**
 * {@hide}
 */
final class DataConnectionTracker extends Handler
{
    private static final String LOG_TAG = "GSM";
    private static final boolean DBG = true;

    /**
     * IDLE: ready to start data connection setup, default state
     * INITING: state of issued setupDefaultPDP() but not finish yet
     * CONNECTING: state of issued startPppd() but not finish yet
     * SCANNING: data connection fails with one apn but other apns are available
     *           ready to start data connection on other apns (before INITING)
     * CONNECTED: IP connection is setup
     * DISCONNECTING: PdpConnection.disconnect() has been called, but PDP
     *                context is not yet deactivated
     * FAILED: data connection fail for all apns settings
     *
     * getDataConnectionState() maps State to DataState
     *      FAILED or IDLE : DISCONNECTED
     *      INITING or CONNECTING or SCANNING: CONNECTING
     *      CONNECTED : CONNECTED or DISCONNECTING
     */
    enum State {
        IDLE,
        INITING,
        CONNECTING,
        SCANNING,
        CONNECTED,
        DISCONNECTING,
        FAILED
    }

    enum Activity {
        NONE,
        DATAIN,
        DATAOUT,
        DATAINANDOUT
    }

    /**
     * Handles changes to the APN db.
     */
    private class ApnChangeObserver extends ContentObserver {
        public ApnChangeObserver () {
            super(mDataConnectionTracker);
        }

        @Override
        public void onChange(boolean selfChange) {
            sendMessage(obtainMessage(EVENT_APN_CHANGED));
        }
    }

    //***** Instance Variables

    GSMPhone phone;
    INetStatService netstat;
    State state = State.IDLE;
    Activity activity = Activity.NONE;
    boolean netStatPollEnabled = false;
    // Indicates baseband will not auto-attach
    private boolean noAutoAttach = false;
    long nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
    Handler mDataConnectionTracker = null;
    private ContentResolver mResolver;

    long txPkts, rxPkts, sentSinceLastRecv;
    int netStatPollPeriod;
    private int mNoRecvPollCount = 0;
    private boolean mPingTestActive = false;
    // Count of PDP reset attempts; reset when we see incoming,
    // call reRegisterNetwork, or pingTest succeeds.
    private int mPdpResetCount = 0;
    private boolean mIsScreenOn = true;

    //useful for debugging
    boolean failNextConnect = false;

    /**
     * allApns holds all apns for this sim spn, retrieved from
     * the Carrier DB.
     *
     * Create once after simcard info is loaded
     */
    private ArrayList<ApnSetting> allApns = 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;

    /**
     * pdpList holds all the PDP connection, i.e. IP Link in GPRS
     */
    private ArrayList<PdpConnection> pdpList;

    /** CID of active PDP */
    int cidActive;

    /** Currently requested APN type */
    private String mRequestedApnType = Phone.APN_TYPE_DEFAULT;

    /** Currently active APN */
    private ApnSetting mActiveApn;

    /** Currently active PdpConnection */
    private PdpConnection mActivePdp;

    private static int APN_DEFAULT_ID = 0;
    private static int APN_MMS_ID = 1;
    private static int APN_NUM_TYPES = 2;

    private boolean[] dataEnabled = new boolean[APN_NUM_TYPES];

    // wifi connection status will be updated by sticky intent
    private boolean mIsWifiConnected = false;

    /** Intent sent when the reconnect alarm fires. */
    private PendingIntent mReconnectIntent = null;

    //***** Constants

    // TODO: Increase this to match the max number of simultaneous
    // PDP contexts we plan to support.
    /**
     * Pool size of PdpConnection objects.
     */
    private static final int PDP_CONNECTION_POOL_SIZE = 1;

    private static final int POLL_PDP_MILLIS = 5 * 1000;
    private static final int RECONNECT_DELAY_INITIAL_MILLIS = 5 * 1000;
    /** Cap out with 1 hour retry interval. */
    private static final int RECONNECT_DELAY_MAX_MILLIS = 60 * 60 * 1000;

    /** Slow poll when attempting connection recovery. */
    private static final int POLL_NETSTAT_SLOW_MILLIS = 5000;

    /** Default ping deadline, in seconds. */
    private final int DEFAULT_PING_DEADLINE = 5;
    /** Default max failure count before attempting to network re-registration. */
    private final int DEFAULT_MAX_PDP_RESET_FAIL = 3;

    /**
     * After detecting a potential connection problem, this is the max number
     * of subsequent polls before attempting a radio reset.  At this point,
     * poll interval is 5 seconds (POLL_NETSTAT_SLOW_MILLIS), so set this to
     * poll for about 2 more minutes.
     */
    private static final int NO_RECV_POLL_LIMIT = 24;

    // 1 sec. default polling interval when screen is on.
    private static final int POLL_NETSTAT_MILLIS = 1000;
    // 10 min. default polling interval when screen is off.
    private static final int POLL_NETSTAT_SCREEN_OFF_MILLIS = 1000*60*10;
    // 2 min for round trip time
    private static final int POLL_LONGEST_RTT = 120 * 1000;
    // 10 for packets without ack
    private static final int NUMBER_SENT_PACKETS_OF_HANG = 10;
    // how long to wait before switching back to default APN
    private static final int RESTORE_DEFAULT_APN_DELAY = 1 * 60 * 1000;
    // system property that can override the above value
    private static final String APN_RESTORE_DELAY_PROP_NAME = "android.telephony.apn-restore";
    // represents an invalid IP address
    private static final String NULL_IP = "0.0.0.0";

    private static final String INTENT_RECONNECT_ALARM = "com.android.internal.telephony.gprs-reconnect";
    private static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason";


    //***** Event Codes
    static final int EVENT_DATA_SETUP_COMPLETE = 1;
    static final int EVENT_RADIO_AVAILABLE = 3;
    static final int EVENT_RECORDS_LOADED = 4;
    static final int EVENT_TRY_SETUP_DATA = 5;
    static final int EVENT_PDP_STATE_CHANGED = 6;
    static final int EVENT_POLL_PDP = 7;
    static final int EVENT_GET_PDP_LIST_COMPLETE = 11;
    static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 12;
    static final int EVENT_VOICE_CALL_STARTED = 14;
    static final int EVENT_VOICE_CALL_ENDED = 15;
    static final int EVENT_GPRS_DETACHED = 19;
    static final int EVENT_LINK_STATE_CHANGED = 20;
    static final int EVENT_ROAMING_ON = 21;
    static final int EVENT_ROAMING_OFF = 22;
    static final int EVENT_ENABLE_NEW_APN = 23;
    static final int EVENT_RESTORE_DEFAULT_APN = 24;
    static final int EVENT_DISCONNECT_DONE = 25;
    static final int EVENT_GPRS_ATTACHED = 26;
    static final int EVENT_START_NETSTAT_POLL = 27;
    static final int EVENT_START_RECOVERY = 28;
    static final int EVENT_APN_CHANGED = 29;

    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) {
                    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;
                }
            }
        }
    };

    /** Watches for changes to the APN db. */
    private ApnChangeObserver apnObserver;

    //***** Constructor

    DataConnectionTracker(GSMPhone phone)
    {
        this.phone = phone;
        phone.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null);
        phone.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
        phone.mSIMRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
        phone.mCM.registerForPDPStateChanged (this, EVENT_PDP_STATE_CHANGED, null);
        phone.mCT.registerForVoiceCallEnded (this, EVENT_VOICE_CALL_ENDED, null);
        phone.mCT.registerForVoiceCallStarted (this, EVENT_VOICE_CALL_STARTED, null);
        phone.mSST.registerForGprsAttached(this, EVENT_GPRS_ATTACHED, null);
        phone.mSST.registerForGprsDetached(this, EVENT_GPRS_DETACHED, null);
        phone.mSST.registerForRoamingOn(this, EVENT_ROAMING_ON, null);
        phone.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);

        this.netstat = INetStatService.Stub.asInterface(ServiceManager.getService("netstat"));

        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);

        phone.getContext().registerReceiver(mIntentReceiver, filter, null, phone.h);


        mDataConnectionTracker = this;
        mResolver = phone.getContext().getContentResolver();

        apnObserver = new ApnChangeObserver();
        phone.getContext().getContentResolver().registerContentObserver(
                Telephony.Carriers.CONTENT_URI, true, apnObserver);

        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());
        dataEnabled[APN_DEFAULT_ID] = !sp.getBoolean(GSMPhone.DATA_DISABLED_ON_BOOT_KEY, false);
        noAutoAttach = !dataEnabled[APN_DEFAULT_ID];
    }

    void setState(State s) {
        if (DBG) log ("setState: " + s);
        if (state != s) {
            if (s == State.INITING) { // request PDP context
                Checkin.updateStats(
                        phone.getContext().getContentResolver(),
                        Checkin.Stats.Tag.PHONE_GPRS_ATTEMPTED, 1, 0.0);
            }

            if (s == State.CONNECTED) { // pppd is up
                Checkin.updateStats(
                        phone.getContext().getContentResolver(),
                        Checkin.Stats.Tag.PHONE_GPRS_CONNECTED, 1, 0.0);
            }
        }

        state = s;

        if (state == State.FAILED) {
            if (waitingApns != null)
                waitingApns.clear(); // when teardown the connection and set to IDLE
        }
    }

    String getStateInString() {
        switch (state) {
            case IDLE:          return "IDLE";
            case INITING:       return "INIT";
            case CONNECTING:    return "CING";
            case SCANNING:      return "SCAN";
            case CONNECTED:     return "CNTD";
            case DISCONNECTING: return "DING";
            case FAILED:        return "FAIL";
            default:            return "ERRO";
        }
    }

    String[] getActiveApnTypes() {
        String[] result;
        if (mActiveApn != null) {
            result = mActiveApn.types;
        } else {
            result = new String[1];
            result[0] = Phone.APN_TYPE_DEFAULT;
        }
        return result;
    }

    String getActiveApnString() {
        String result = null;
        if (mActiveApn != null) {
            result = mActiveApn.apn;
        }
        return result;
    }

    /**
     * Ensure that we are connected to an APN of the specified type.
     * @param type the APN type (currently the only valid value
     * is {@link Phone#APN_TYPE_MMS})
     * @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.
     */
    int enableApnType(String type) {
        if (!TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
            return Phone.APN_REQUEST_FAILED;
        }
        // If already active, return
        Log.d(LOG_TAG, "enableApnType("+type+")");
        if (isApnTypeActive(type)) {
            setEnabled(type, true);
            removeMessages(EVENT_RESTORE_DEFAULT_APN);
            /**
             * We're being asked to enable a non-default APN that's already in use.
             * This means we should restart the timer that will automatically
             * switch back to the default APN and disable the non-default APN
             * when it expires.
             */
            sendMessageDelayed(
                    obtainMessage(EVENT_RESTORE_DEFAULT_APN),
                    getRestoreDefaultApnDelay());
            if (state == State.INITING) return Phone.APN_REQUEST_STARTED;
            else if (state == State.CONNECTED) return Phone.APN_ALREADY_ACTIVE;
        }

        if (!isApnTypeAvailable(type)) {
            return Phone.APN_TYPE_NOT_AVAILABLE;
        }

        setEnabled(type, true);
        mRequestedApnType = type;
        sendMessage(obtainMessage(EVENT_ENABLE_NEW_APN));
        return Phone.APN_REQUEST_STARTED;
    }

    /**
     * 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 value currently is {@link Phone#APN_TYPE_MMS}.
     * @return
     */
    int disableApnType(String type) {
        Log.d(LOG_TAG, "disableApnType("+type+")");
        if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
            removeMessages(EVENT_RESTORE_DEFAULT_APN);
            setEnabled(type, false);
            if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
                if (dataEnabled[APN_DEFAULT_ID]) {
                    return Phone.APN_ALREADY_ACTIVE;
                } else {
                    cleanUpConnection(true, Phone.REASON_DATA_DISABLED);
                    return Phone.APN_REQUEST_STARTED;
                }
            } else {
                /*
                 * Note that if default data is disabled, the following
                 * has the effect of disabling the MMS APN, and then
                 * ignoring the request to enable the default APN.
                 * The net result is that data is completely disabled.
                 */
                sendMessage(obtainMessage(EVENT_RESTORE_DEFAULT_APN));
                return Phone.APN_REQUEST_STARTED;
            }
        } else {
            return Phone.APN_REQUEST_FAILED;
        }
    }

    /**
     * The data connection is expected to be setup while device
     *  1. has sim card
     *  2. registered to gprs service
     *  3. user doesn't explicitly disable data service
     *  4. wifi is not on
     *
     * @return false while no data connection if all above requirements are met.
     */
    boolean isDataConnectionAsDesired() {
        boolean roaming = phone.getServiceState().getRoaming();

        if (phone.mSIMRecords.getRecordsLoaded() &&
            phone.mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE &&
            (!roaming || getDataOnRoamingEnabled()) &&
            !mIsWifiConnected ) {
            return (state == State.CONNECTED);
        }
        return true;
    }

    private boolean isApnTypeActive(String type) {
        // TODO: to support simultaneous, mActiveApn can be a List instead.
        return mActiveApn != null && mActiveApn.canHandleType(type);
    }

    private boolean isApnTypeAvailable(String type) {
        if (allApns != null) {
            for (ApnSetting apn : allApns) {
                if (apn.canHandleType(type)) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean isEnabled(String apnType) {
        if (TextUtils.equals(apnType, Phone.APN_TYPE_DEFAULT)) {
            return dataEnabled[APN_DEFAULT_ID];
        } else if (TextUtils.equals(apnType, Phone.APN_TYPE_MMS)) {
            return dataEnabled[APN_MMS_ID];
        } else {
            return false;
        }
    }

    private void setEnabled(String apnType, boolean enable) {
        Log.d(LOG_TAG, "setEnabled(" + apnType + ", " + enable + ')');
        if (TextUtils.equals(apnType, Phone.APN_TYPE_DEFAULT)) {
            dataEnabled[APN_DEFAULT_ID] = enable;
        } else if (TextUtils.equals(apnType, Phone.APN_TYPE_MMS)) {
            dataEnabled[APN_MMS_ID] = enable;
        }
        Log.d(LOG_TAG, "dataEnabled[DEFAULT_APN]=" + dataEnabled[APN_DEFAULT_ID] +
                " dataEnabled[MMS_APN]=" + dataEnabled[APN_MMS_ID]);
    }

    /**
     * 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) {
        boolean isEnabled = isEnabled(Phone.APN_TYPE_DEFAULT);
        Log.d(LOG_TAG, "setDataEnabled("+enable+") isEnabled=" + isEnabled);
        if (!isEnabled && enable) {
            setEnabled(Phone.APN_TYPE_DEFAULT, true);
            // trySetupData() will be a no-op if we are currently
            // connected to the MMS APN
            return trySetupData(Phone.REASON_DATA_ENABLED);
        } else if (!enable) {
            setEnabled(Phone.APN_TYPE_DEFAULT, false);
            // Don't tear down if there is an active APN and it handles MMS.
            // TODO: This isn't very general.
            if (!isApnTypeActive(Phone.APN_TYPE_MMS) || !isEnabled(Phone.APN_TYPE_MMS)) {
                cleanUpConnection(true, Phone.REASON_DATA_DISABLED);
                return true;
            }
            return false;
        } else // isEnabled && enable
            return true;
    }

    /**
     * Report the current state of data connectivity (enabled or disabled) for
     * the default APN.
     * @return {@code false} if data connectivity has been explicitly disabled,
     * {@code true} otherwise.
     */
    public boolean getDataEnabled() {
        return dataEnabled[APN_DEFAULT_ID];
    }

    /**
     * Report on whether data connectivity is enabled for any APN.
     * @return {@code false} if data connectivity has been explicitly disabled,
     * {@code true} otherwise.
     */
    public boolean getAnyDataEnabled() {
        return dataEnabled[APN_DEFAULT_ID] || dataEnabled[APN_MMS_ID];
    }

    //The data roaming setting is now located in the shared preferences.
    //  See if the requested preference value is the same as that stored in
    //  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.DATA_ROAMING, enabled ? 1 : 0);
        }
        Message roamingMsg = phone.getServiceState().getRoaming() ?
            obtainMessage(EVENT_ROAMING_ON) : obtainMessage(EVENT_ROAMING_OFF);
        sendMessage(roamingMsg);
    }

    //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;
        } catch (SettingNotFoundException snfe) {
            return false;
        }
    }

    public ArrayList<PdpConnection> getAllPdps() {
        ArrayList<PdpConnection> pdps = (ArrayList<PdpConnection>)pdpList.clone();
        return pdps;
    }

    private boolean isDataAllowed() {
        boolean roaming = phone.getServiceState().getRoaming();
        return getAnyDataEnabled() && (!roaming || getDataOnRoamingEnabled());
    }

    //****** Called from ServiceStateTracker
    /**
     * Invoked when ServiceStateTracker observes a transition from GPRS
     * attach to detach.
     */
    private void onGprsDetached()
    {
        /*
         * We presently believe it is unnecessary to tear down the PDP context
         * when GPRS detaches, but we should stop the network polling.
         */
        stopNetStatPoll();
        phone.notifyDataConnection(Phone.REASON_GPRS_DETACHED);
    }

    private void onGprsAttached() {
        if (state == State.CONNECTED) {
            startNetStatPoll();
            phone.notifyDataConnection(Phone.REASON_GPRS_ATTACHED);
        } else {
            if (state == State.FAILED) {
                cleanUpConnection(false, Phone.REASON_GPRS_ATTACHED);
                nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
            }
            trySetupData(Phone.REASON_GPRS_ATTACHED);
        }
    }

    private boolean trySetupData(String reason)
    {
        if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason));

        if (phone.getSimulatedRadioControl() != null) {
            // Assume data is connected on the simulator
            // FIXME  this can be improved
            setState(State.CONNECTED);
            phone.notifyDataConnection(reason);

            Log.i(LOG_TAG, "(fix?) We're on the simulator; assuming data is connected");
            return true;
        }

        int gprsState = phone.mSST.getCurrentGprsState();
        boolean roaming = phone.getServiceState().getRoaming();

        if ((state == State.IDLE || state == State.SCANNING)
                && (gprsState == ServiceState.STATE_IN_SERVICE || noAutoAttach)
                && phone.mSIMRecords.getRecordsLoaded()
                && ( phone.mSST.isConcurrentVoiceAndData() ||
                     phone.getState() == Phone.State.IDLE )
                && isDataAllowed()) {

            if (state == State.IDLE) {
                waitingApns = buildWaitingApns();
                if (waitingApns.isEmpty()) {
                    if (DBG) log("No APN found");
                    notifyNoData(PdpConnection.PdpFailCause.BAD_APN);
                    return false;
                } else {
                    log ("Create from allApns : " + apnListToString(allApns));
                }
            }

            if (DBG) {
                log ("Setup watingApns : " + apnListToString(waitingApns));
            }
            return setupData(reason);
        } else {
            if (DBG)
                log("trySetupData: Not ready for data: " +
                    " dataState=" + state +
                    " gprsState=" + gprsState +
                    " sim=" + phone.mSIMRecords.getRecordsLoaded() +
                    " UMTS=" + phone.mSST.isConcurrentVoiceAndData() +
                    " phoneState=" + phone.getState() +
                    " dataEnabled=" + getAnyDataEnabled() +
                    " roaming=" + roaming +
                    " dataOnRoamingEnable=" + getDataOnRoamingEnabled());
            return false;
        }
    }

    /**
     * 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 PdpConnection should be
     * disconnected.
     * @param reason reason for the clean up.
     */
    private void cleanUpConnection(boolean tearDown, String reason) {
        if (DBG) log("Clean up connection due to " + reason);

        // Clear the reconnect alarm, if set.
        if (mReconnectIntent != null) {
            AlarmManager am =
                (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
            am.cancel(mReconnectIntent);
            mReconnectIntent = null;
        }

        for (PdpConnection pdp : pdpList) {
            if (tearDown) {
                Message msg = obtainMessage(EVENT_DISCONNECT_DONE, reason);
                pdp.disconnect(msg);
            } else {
                pdp.clearSettings();
            }
        }
        stopNetStatPoll();

        /*
         * If we've been asked to tear down the connection,
         * set the state to DISCONNECTING. However, there's
         * a race that can occur if for some reason we were
         * already in the IDLE state. In that case, the call
         * to pdp.disconnect() above will immediately post
         * a message to the handler thread that the disconnect
         * is done, and if the handler runs before the code
         * below does, the handler will have set the state to
         * IDLE before the code below runs. If we didn't check
         * for that, future calls to trySetupData would fail,
         * and we would never get out of the DISCONNECTING state.
         */
        if (!tearDown) {
            setState(State.IDLE);
            phone.notifyDataConnection(reason);
            mActiveApn = null;
        } else if (state != State.IDLE) {
            setState(State.DISCONNECTING);
        }
    }

    /**
     * @param types comma delimited list of APN types
     * @return array of APN types
     */
    private String[] parseTypes(String types) {
        String[] result;
        // If unset, set to DEFAULT.
        if (types == null || types.equals("")) {
            result = new String[1];
            result[0] = Phone.APN_TYPE_ALL;
        } else {
            result = types.split(",");
        }
        return result;
    }

    private ArrayList<ApnSetting> createApnList(Cursor cursor) {
        ArrayList<ApnSetting> result = new ArrayList<ApnSetting>();
        if (cursor.moveToFirst()) {
            do {
                String[] types = parseTypes(
                        cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.TYPE)));
                ApnSetting apn = new ApnSetting(
                        cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)),
                        cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)),
                        cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY)),
                        cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT)),
                        cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC)),
                        cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY)),
                        cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT)),
                        cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)),
                        cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)),
                        types);
                result.add(apn);
            } while (cursor.moveToNext());
        }
        return result;
    }

    private PdpConnection findFreePdp() {
        for (PdpConnection pdp : pdpList) {
            if (pdp.getState() == PdpConnection.PdpState.INACTIVE) {
                return pdp;
            }
        }
        return null;
    }

    private boolean setupData(String reason) {
        ApnSetting apn;
        PdpConnection pdp;

        apn = getNextApn();
        if (apn == null) return false;
        pdp = findFreePdp();
        if (pdp == null) {
            if (DBG) log("setupData: No free PdpConnection found!");
            return false;
        }
        mActiveApn = apn;
        mActivePdp = pdp;

        Message msg = obtainMessage();
        msg.what = EVENT_DATA_SETUP_COMPLETE;
        msg.obj = reason;
        pdp.connect(apn, msg);

        setState(State.INITING);
        phone.notifyDataConnection(reason);
        return true;
    }

    String getInterfaceName(String apnType) {
        if (mActivePdp != null
                && (apnType == null || mActiveApn.canHandleType(apnType))) {
            return mActivePdp.getInterface();
        }
        return null;
    }

    String getIpAddress(String apnType) {
        if (mActivePdp != null
                && (apnType == null || mActiveApn.canHandleType(apnType))) {
            return mActivePdp.getIpAddress();
        }
        return null;
    }

    String getGateway(String apnType) {
        if (mActivePdp != null
                && (apnType == null || mActiveApn.canHandleType(apnType))) {
            return mActivePdp.getGatewayAddress();
        }
        return null;
    }

    String[] getDnsServers(String apnType) {
        if (mActivePdp != null
                && (apnType == null || mActiveApn.canHandleType(apnType))) {
            return mActivePdp.getDnsServers();
        }
        return null;
    }

    private boolean
    pdpStatesHasCID (ArrayList<PDPContextState> 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<PDPContextState> states, int cid)
    {
        for (int i = 0, s = states.size() ; i < s ; i++) {
            if (states.get(i).cid == cid) return states.get(i).active;
        }

        return false;
    }

    /**
     * Handles changes to the APN database.
     */
    private void onApnChanged() {
        boolean isConnected;

        isConnected = (state != State.IDLE && state != State.FAILED);

        // TODO: It'd be nice to only do this if the changed entrie(s)
        // match the current operator.
        createAllApnList();
        if (state != State.DISCONNECTING) {
            cleanUpConnection(isConnected, Phone.REASON_APN_CHANGED);
            if (!isConnected) {
                trySetupData(Phone.REASON_APN_CHANGED);
            }
        }
    }

    /**
     * @param explicitPoll if true, indicates that *we* polled for this
     * update while state == CONNECTED rather than having it delivered
     * via an unsolicited response (which could have happened at any
     * previous state
     */
    private void
    onPdpStateChanged (AsyncResult ar, boolean explicitPoll)
    {
        ArrayList<PDPContextState> pdpStates;

        pdpStates = (ArrayList<PDPContextState>)(ar.result);

        if (ar.exception != null) {
            // This is probably "radio not available" or something
            // of that sort. If so, the whole connection is going
            // to come down soon anyway
            return;
        }


        // This is how things are supposed to work:
        // The PDP list is supposed to be empty of the CID
        // when it disconnects

        if (state == State.CONNECTED
                && !pdpStatesHasCID(pdpStates, cidActive)) {

            // It looks like the PDP context has deactivated
            // Tear everything down and try to reconnect

            Log.i(LOG_TAG, "PDP connection has dropped. Reconnecting");

            // Add an event log when the network drops PDP
            int cid = -1;
            GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
            if (loc != null) cid = loc.getCid();

            EventLog.List val = new EventLog.List(cid,
                    TelephonyManager.getDefault().getNetworkType());

            EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP, val);

            cleanUpConnection(true, null);

            return;
        }

        if (true) {
            //
            // Workaround for issue #655426
            //

            // --------------------------

            // This is how some things work now: 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.
            //
            // 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 (state == State.CONNECTED
                    && !pdpStatesHasActiveCID(pdpStates, cidActive)) {

                if (!explicitPoll) {
                    // We think it disconnected but aren't sure...poll from our side
                    phone.mCM.getPDPContextList(
                        this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
                } else {
                    Log.i(LOG_TAG, "PDP connection has dropped (active=false case). "
                                    + " Reconnecting");

                    // Log the network drop on the event log.
                    int cid = -1;
                    GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
                    if (loc != null) cid = loc.getCid();

                    EventLog.List val = new EventLog.List(cid,
                            TelephonyManager.getDefault().getNetworkType());

                    EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP, val);

                    cleanUpConnection(true, null);
                }
            }
        }
    }

    private void notifyDefaultData(String reason) {
        setupDnsProperties();
        setState(State.CONNECTED);
        phone.notifyDataConnection(reason);
        startNetStatPoll();
        // reset reconnect timer
        nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
    }

    private void setupDnsProperties() {
        int mypid = android.os.Process.myPid();
        String[] servers = getDnsServers(null);
        String propName;
        String propVal;
        int count;

        count = 0;
        for (int i = 0; i < servers.length; i++) {
            String serverAddr = servers[i];
            if (!TextUtils.equals(serverAddr, "0.0.0.0")) {
                SystemProperties.set("net.dns" + (i+1) + "." + mypid, serverAddr);
                count++;
            }
        }
        for (int i = count+1; i <= 4; i++) {
            propName = "net.dns" + i + "." + mypid;
            propVal = SystemProperties.get(propName);
            if (propVal.length() != 0) {
                SystemProperties.set(propName, "");
            }
        }
        /*
         * Bump the property that tells the name resolver library
         * to reread the DNS server list from the properties.
         */
        propVal = SystemProperties.get("net.dnschange");
        if (propVal.length() != 0) {
            try {
                int n = Integer.parseInt(propVal);
                SystemProperties.set("net.dnschange", "" + (n+1));
            } catch (NumberFormatException e) {
            }
        }
    }

    /**
     * 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;
        mNoRecvPollCount = 0;
    }

    private void doRecovery() {
        if (state == State.CONNECTED) {
            int maxPdpReset = Settings.Gservices.getInt(mResolver,
                    Settings.Gservices.PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT,
                    DEFAULT_MAX_PDP_RESET_FAIL);
            if (mPdpResetCount < maxPdpReset) {
                mPdpResetCount++;
                EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_RESET, sentSinceLastRecv);
                cleanUpConnection(true, Phone.REASON_PDP_RESET);
            } else {
                mPdpResetCount = 0;
                EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_REREGISTER_NETWORK, sentSinceLastRecv);
                phone.mSST.reRegisterNetwork(null);
            }
            // TODO: Add increasingly drastic recovery steps, eg,
            // reset the radio, reset the device.
        }
    }

    private void
    startNetStatPoll()
    {
        if (state == State.CONNECTED && mPingTestActive == false && netStatPollEnabled == false) {
            Log.d(LOG_TAG, "[DataConnection] Start poll NetStat");
            resetPollStats();
            netStatPollEnabled = true;
            mPollNetStat.run();
        }
    }

    private void
    stopNetStatPoll()
    {
        netStatPollEnabled = false;
        removeCallbacks(mPollNetStat);
        Log.d(LOG_TAG, "[DataConnection] Stop poll NetStat");
    }

    private void
    restartRadio()
    {
        Log.d(LOG_TAG, "************TURN OFF RADIO**************");
        cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
        phone.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
         * RADIO_STATE_CHANGED notification for the power off.  And if the
         * desired power state has changed in the interim, we don't want to
         * override it with an unconditional power on.
         */

        int reset = Integer.parseInt(SystemProperties.get("net.ppp.reset-by-timeout", "0"));
        SystemProperties.set("net.ppp.reset-by-timeout", String.valueOf(reset+1));
    }

    Runnable mPollNetStat = new Runnable()
    {

        public void run() {
            long sent, received;
            long preTxPkts = -1, preRxPkts = -1;

            Activity newActivity;

            preTxPkts = txPkts;
            preRxPkts = rxPkts;

            try {
                txPkts = netstat.getMobileTxPackets();
                rxPkts = netstat.getMobileRxPackets();
            } catch (RemoteException e) {
                txPkts = 0;
                rxPkts = 0;
            }

            //Log.d(LOG_TAG, "rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts));

            if (netStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) {
                sent = txPkts - preTxPkts;
                received = rxPkts - preRxPkts;

                if ( sent > 0 && received > 0 ) {
                    sentSinceLastRecv = 0;
                    newActivity = Activity.DATAINANDOUT;
                    mPdpResetCount = 0;
                } else if (sent > 0 && received == 0) {
                    if (phone.mCT.state == Phone.State.IDLE) {
                        sentSinceLastRecv += sent;
                    } else {
                        sentSinceLastRecv = 0;
                    }
                    newActivity = Activity.DATAOUT;
                } else if (sent == 0 && received > 0) {
                    sentSinceLastRecv = 0;
                    newActivity = Activity.DATAIN;
                    mPdpResetCount = 0;
                } else if (sent == 0 && received == 0) {
                    newActivity = Activity.NONE;
                } else {
                    sentSinceLastRecv = 0;
                    newActivity = Activity.NONE;
                }

                if (activity != newActivity && mIsScreenOn) {
                    activity = newActivity;
                    phone.notifyDataActivity();
                }
            }

            int watchdogTrigger = Settings.Gservices.getInt(mResolver,
                    Settings.Gservices.PDP_WATCHDOG_TRIGGER_PACKET_COUNT, NUMBER_SENT_PACKETS_OF_HANG);

            if (sentSinceLastRecv >= watchdogTrigger) {
                // we already have NUMBER_SENT_PACKETS sent without ack
                if (mNoRecvPollCount == 0) {
                    EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_RADIO_RESET_COUNTDOWN_TRIGGERED,
                            sentSinceLastRecv);
                }

                int noRecvPollLimit = Settings.Gservices.getInt(mResolver,
                        Settings.Gservices.PDP_WATCHDOG_ERROR_POLL_COUNT, NO_RECV_POLL_LIMIT);

                if (mNoRecvPollCount < noRecvPollLimit) {
                    // 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.getPDPContextList(obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));

                    mNoRecvPollCount++;

                    // Slow down the poll interval to let things happen
                    netStatPollPeriod = Settings.Gservices.getInt(mResolver,
                            Settings.Gservices.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS, POLL_NETSTAT_SLOW_MILLIS);
                } else {
                    if (DBG) log("Sent " + String.valueOf(sentSinceLastRecv) +
                                        " 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() {
                        public void run() {
                            runPingTest();
                        }
                    };
                    mPingTestActive = true;
                    pingTest.start();
                }
            } else {
                mNoRecvPollCount = 0;
                if (mIsScreenOn) {
                    netStatPollPeriod = Settings.Gservices.getInt(mResolver,
                            Settings.Gservices.PDP_WATCHDOG_POLL_INTERVAL_MS, POLL_NETSTAT_MILLIS);
                } else {
                    netStatPollPeriod = Settings.Gservices.getInt(mResolver,
                            Settings.Gservices.PDP_WATCHDOG_LONG_POLL_INTERVAL_MS,
                            POLL_NETSTAT_SCREEN_OFF_MILLIS);
                }
            }

            if (netStatPollEnabled) {
                mDataConnectionTracker.postDelayed(this, netStatPollPeriod);
            }
        }
    };

    private void runPingTest () {
        int status = -1;
        try {
            String address = Settings.Gservices.getString(mResolver,
                    Settings.Gservices.PDP_WATCHDOG_PING_ADDRESS);
            int deadline = Settings.Gservices.getInt(mResolver,
                        Settings.Gservices.PDP_WATCHDOG_PING_DEADLINE, DEFAULT_PING_DEADLINE);
            if (DBG) log("pinging " + address + " for " + deadline + "s");
            if (address != null && !NULL_IP.equals(address)) {
                Process p = Runtime.getRuntime()
                                .exec("ping -c 1 -i 1 -w "+ deadline + " " + address);
                status = p.waitFor();
            }
        } catch (IOException e) {
            Log.w(LOG_TAG, "ping failed: IOException");
        } catch (Exception e) {
            Log.w(LOG_TAG, "exception trying to ping");
        }

        if (status == 0) {
            // ping succeeded.  False alarm.  Reset netStatPoll.
            // ("-1" for this event indicates a false alarm)
            EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_RESET, -1);
            mPdpResetCount = 0;
            sendMessage(obtainMessage(EVENT_START_NETSTAT_POLL));
        } else {
            // ping failed.  Proceed with recovery.
            sendMessage(obtainMessage(EVENT_START_RECOVERY));
        }
    }

    /**
     * Returns true if the last fail cause is something that
     * seems like it deserves an error notification.
     * Transient errors are ignored
     */
    private boolean
    shouldPostNotification(PdpConnection.PdpFailCause  cause)
    {
        boolean shouldPost = true;
        // TODO CHECK
        // if (dataLink != null) {
        //    shouldPost = dataLink.getLastLinkExitCode() != DataLink.EXIT_OPEN_FAILED;
        //}
        return (shouldPost && cause != PdpConnection.PdpFailCause.UNKNOWN);
    }

    private void reconnectAfterFail(PdpFailCause lastFailCauseCode, String reason) {
        if (state == State.FAILED) {
            Log.d(LOG_TAG, "PDP activate failed. Scheduling next attempt for "
                    + (nextReconnectDelay / 1000) + "s");

            AlarmManager am =
                (AlarmManager) phone.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);
            am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                    SystemClock.elapsedRealtime() + nextReconnectDelay,
                    mReconnectIntent);

            // double it for next time
            nextReconnectDelay *= 2;
            if (nextReconnectDelay > RECONNECT_DELAY_MAX_MILLIS) {
                nextReconnectDelay = RECONNECT_DELAY_MAX_MILLIS;
            }

            if (!shouldPostNotification(lastFailCauseCode)) {
                Log.d(LOG_TAG,"NOT Posting GPRS Unavailable notification "
                                + "-- likely transient error");
            } else {
                notifyNoData(lastFailCauseCode);
            }
        }
    }

    private void notifyNoData(PdpConnection.PdpFailCause lastFailCauseCode) {
        setState(State.FAILED);
    }


    private void log(String s) {
        Log.d(LOG_TAG, "[DataConnectionTracker] " + s);
    }

    //***** Overridden from Handler
    public void
    handleMessage (Message msg)
    {
        AsyncResult ar;
        String reason = null;

        switch (msg.what) {
            case EVENT_RECORDS_LOADED:
                createAllApnList();
                if (state == State.FAILED) {
                    cleanUpConnection(false, null);
                }
                sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
                break;

            case EVENT_ENABLE_NEW_APN:
                // TODO:  To support simultaneous PDP contexts, this should really only call
                // cleanUpConnection if it needs to free up a PdpConnection.
                reason = Phone.REASON_APN_SWITCHED;
                cleanUpConnection(true, reason);
                break;

            case EVENT_TRY_SETUP_DATA:
                trySetupData(reason);
                break;

            case EVENT_RESTORE_DEFAULT_APN:
                if (DBG) Log.d(LOG_TAG, "Restore default APN");
                setEnabled(Phone.APN_TYPE_MMS, false);
                if (!isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
                    cleanUpConnection(true, Phone.REASON_RESTORE_DEFAULT_APN);
                    mRequestedApnType = Phone.APN_TYPE_DEFAULT;
                }
                break;

            case EVENT_ROAMING_OFF:
                trySetupData(Phone.REASON_ROAMING_OFF);
                break;

            case EVENT_GPRS_DETACHED:
                onGprsDetached();
                break;

            case EVENT_GPRS_ATTACHED:
                onGprsAttached();
                break;

            case EVENT_ROAMING_ON:
                if (getDataOnRoamingEnabled()) {
                    trySetupData(Phone.REASON_ROAMING_ON);
                } else {
                    if (DBG) log("Tear down data connection on roaming.");
                    cleanUpConnection(true, Phone.REASON_ROAMING_ON);
                }
                break;

            case EVENT_RADIO_AVAILABLE:
                if (phone.getSimulatedRadioControl() != null) {
                    // Assume data is connected on the simulator
                    // FIXME  this can be improved
                    setState(State.CONNECTED);
                    phone.notifyDataConnection(null);


                    Log.i(LOG_TAG, "We're on the simulator; assuming data is connected");
                }

                if (state != State.IDLE) {
                    cleanUpConnection(true, null);
                }
            break;

            case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
                // Make sure our reconnect delay starts at the initial value
                // next time the radio comes on
                nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;

                if (phone.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");
                } else {
                    if (DBG) log("Radio is off and clean up all connection");
                    // TODO: Should we reset mRequestedApnType to "default"?
                    cleanUpConnection(false, Phone.REASON_RADIO_TURNED_OFF);
                }
            break;

            case EVENT_DATA_SETUP_COMPLETE:
                ar = (AsyncResult) msg.obj;
                if (ar.userObj instanceof String) {
                    reason = (String) ar.userObj;
                }

                if (ar.exception == null) {
                    // everything is setup

                    // arg1 contains CID for this PDP context
                    cidActive = msg.arg1;
                    /*
                     * We may have switched away from the default PDP context
                     * in order to enable a "special" APN (e.g., for MMS
                     * traffic). Set a timer to switch back and/or disable the
                     * special APN, so that a negligient application doesn't
                     * permanently prevent data connectivity. What we are
                     * protecting against here is not malicious apps, but
                     * rather an app that inadvertantly fails to reset to the
                     * default APN, or that dies before doing so.
                     */
                    if (dataEnabled[APN_MMS_ID]) {
                        removeMessages(EVENT_RESTORE_DEFAULT_APN);
                        sendMessageDelayed(
                                obtainMessage(EVENT_RESTORE_DEFAULT_APN),
                                getRestoreDefaultApnDelay());
                    }
                    if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
                        SystemProperties.set("gsm.defaultpdpcontext.active", "true");
                    } else {
                        SystemProperties.set("gsm.defaultpdpcontext.active", "false");
                    }
                    notifyDefaultData(reason);

                    // TODO: For simultaneous PDP support, we need to build another
                    // trigger another TRY_SETUP_DATA for the next APN type.  (Note
                    // that the existing connection may service that type, in which
                    // case we should try the next type, etc.
                } else {
                    PdpConnection.PdpFailCause cause;
                    cause = (PdpConnection.PdpFailCause) (ar.result);
                    if(DBG)
                        log("PDP setup failed " + cause);
                    // Log this failure to the Event Logs.
                    if (cause == PdpConnection.PdpFailCause.BAD_APN ||
                        cause == PdpConnection.PdpFailCause.BAD_PAP_SECRET ||
                        cause == PdpConnection.PdpFailCause.BARRED ||
                        cause == PdpConnection.PdpFailCause.RADIO_ERROR_RETRY ||
                        cause == PdpConnection.PdpFailCause.SUSPENED_TEMPORARY ||
                        cause == PdpConnection.PdpFailCause.UNKNOWN ||
                        cause == PdpConnection.PdpFailCause.USER_AUTHENTICATION) {
                        int cid = -1;
                        GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
                        if (loc != null) cid = loc.getCid();

                        EventLog.List val = new EventLog.List(
                            cause.ordinal(), cid,
                            TelephonyManager.getDefault().getNetworkType());
                        EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_RADIO_PDP_SETUP_FAIL, val);
                    }
                    // No try for permanent failure
                    if (cause.isPermanentFail()) {
                        notifyNoData(cause);
                    }

                    if (tryNextApn(cause)) {
                        waitingApns.remove(0);
                        if (waitingApns.isEmpty()) {
                            // No more to try, start delayed retry
                            startDelayedRetry(cause, reason);
                        } else {
                            // we still have more apns to try
                            setState(State.SCANNING);
                            trySetupData(reason);
                        }
                    } else {
                        startDelayedRetry(cause, reason);
                    }
                }
            break;

            case EVENT_DISCONNECT_DONE:
                if(DBG) log("EVENT_DISCONNECT_DONE");
                ar = (AsyncResult) msg.obj;
                if (ar.userObj instanceof String) {
                    reason = (String) ar.userObj;
                }
                setState(State.IDLE);
                phone.notifyDataConnection(reason);
                mActiveApn = null;
                trySetupData(reason);
                break;

            case EVENT_PDP_STATE_CHANGED:
                ar = (AsyncResult) msg.obj;

                onPdpStateChanged(ar, false);
            break;

            case EVENT_GET_PDP_LIST_COMPLETE:
                ar = (AsyncResult) msg.obj;

                onPdpStateChanged(ar, true);
            break;

            case EVENT_POLL_PDP:
                /* See comment in startPeriodicPdpPoll */
                ar = (AsyncResult) msg.obj;

                if (!(state == State.CONNECTED)) {
                    // not connected; don't poll anymore
                    break;
                }

                phone.mCM.getPDPContextList(this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));

                sendMessageDelayed(obtainMessage(EVENT_POLL_PDP),
                                   POLL_PDP_MILLIS);
            break;

            case EVENT_VOICE_CALL_STARTED:
                if (state == State.CONNECTED &&
                        !phone.mSST.isConcurrentVoiceAndData()) {
                    stopNetStatPoll();
                    phone.notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
                }
            break;

            case EVENT_VOICE_CALL_ENDED:
                if (state == State.CONNECTED) {
                    if (!phone.mSST.isConcurrentVoiceAndData()) {
                        startNetStatPoll();
                        phone.notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
                    } else {
                        // clean slate after call end.
                        resetPollStats();
                    }
                } else {
                    // in case data setup was attempted when we were on a voice call
                    trySetupData(Phone.REASON_VOICE_CALL_ENDED);
                }
            break;

            case EVENT_START_NETSTAT_POLL:
                mPingTestActive = false;
                startNetStatPoll();
                break;

            case EVENT_START_RECOVERY:
                mPingTestActive = false;
                doRecovery();
                break;

            case EVENT_APN_CHANGED:
                onApnChanged();
                break;
        }
    }

    private boolean tryNextApn(PdpFailCause cause) {
        return (cause != PdpFailCause.RADIO_NOT_AVIALABLE)
            && (cause != PdpFailCause.RADIO_OFF)
            && (cause != PdpFailCause.RADIO_ERROR_RETRY)
            && (cause != PdpFailCause.NO_SIGNAL)
            && (cause != PdpFailCause.SIM_LOCKED);
    }

    private int getRestoreDefaultApnDelay() {
        String restoreApnDelayStr = SystemProperties.get(APN_RESTORE_DELAY_PROP_NAME);

        if (restoreApnDelayStr != null && restoreApnDelayStr.length() != 0) {
            try {
                return Integer.valueOf(restoreApnDelayStr);
            } catch (NumberFormatException e) {
            }
        }
        return RESTORE_DEFAULT_APN_DELAY;
   }

    /**
     * Based on the sim operator numeric, create a list for all possible pdps
     * with all apns associated with that pdp
     *
     *
     */
    private void createAllApnList() {
        allApns = new ArrayList<ApnSetting>();
        String operator = phone.mSIMRecords.getSIMOperatorNumeric();

        if (operator != null) {
            String selection = "numeric = '" + operator + "'";

            Cursor cursor = phone.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 PdpConnection
                    // object.  Not used on current platform (no ppp).
                    //PdpConnection pdp = pdpList.get(pdp_name);
                    //if (pdp != null && pdp.dataLink != null) {
                    //    pdp.dataLink.setPasswordInfo(cursor);
                    //}
                }
                cursor.close();
            }
        }

        if (allApns.isEmpty()) {
            if (DBG) log("No APN found for carrier: " + operator);
            notifyNoData(PdpConnection.PdpFailCause.BAD_APN);
        }
    }

    private void createAllPdpList() {
        pdpList = new ArrayList<PdpConnection>();
        PdpConnection pdp;

        for (int i = 0; i < PDP_CONNECTION_POOL_SIZE; i++) {
            pdp = new PdpConnection(phone);
            pdpList.add(pdp);
         }
    }

    /**
     *
     * @return waitingApns list to be used to create PDP
     *          error when waitingApns.isEmpty()
     */
    private ArrayList<ApnSetting> buildWaitingApns() {
        ArrayList<ApnSetting> apnList = new ArrayList<ApnSetting>();

        if (allApns != null) {
            for (ApnSetting apn : allApns) {
                if (apn.canHandleType(mRequestedApnType)) {
                    apnList.add(apn);
                }
            }
        }
        return apnList;
    }

    /**
     * Get next apn in waitingApns
     * @return the first apn found in waitingApns, null if none
     */
    private ApnSetting getNextApn() {
        ArrayList<ApnSetting> list = waitingApns;
        ApnSetting apn = null;

        if (list != null) {
            if (!list.isEmpty()) {
                apn = list.get(0);
            }
        }
        return apn;
    }

    private String apnListToString (ArrayList<ApnSetting> apns) {
        StringBuilder result = new StringBuilder();
        for (int i = 0, size = apns.size(); i < size; i++) {
            result.append('[')
                  .append(apns.get(i).toString())
                  .append(']');
        }
        return result.toString();
    }

    private void startDelayedRetry(PdpConnection.PdpFailCause cause, String reason) {
        notifyNoData(cause);
        if (mRequestedApnType != Phone.APN_TYPE_DEFAULT) {
            sendMessage(obtainMessage(EVENT_RESTORE_DEFAULT_APN));
        }
        else {
            reconnectAfterFail(cause, reason);
        }
    }
}
