Home | History | Annotate | Download | only in telephony
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.internal.telephony;
     18 
     19 import android.app.PendingIntent;
     20 import android.content.BroadcastReceiver;
     21 import android.content.ContentResolver;
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.content.IntentFilter;
     25 import android.content.SharedPreferences;
     26 import android.database.ContentObserver;
     27 import android.net.LinkCapabilities;
     28 import android.net.LinkProperties;
     29 import android.net.NetworkInfo;
     30 import android.net.TrafficStats;
     31 import android.net.wifi.WifiManager;
     32 import android.os.AsyncResult;
     33 import android.os.Bundle;
     34 import android.os.Handler;
     35 import android.os.Message;
     36 import android.os.Messenger;
     37 import android.os.SystemClock;
     38 import android.os.SystemProperties;
     39 import android.preference.PreferenceManager;
     40 import android.provider.Settings;
     41 import android.provider.Settings.SettingNotFoundException;
     42 import android.telephony.ServiceState;
     43 import android.telephony.TelephonyManager;
     44 import android.text.TextUtils;
     45 import android.util.Log;
     46 
     47 import com.android.internal.R;
     48 import com.android.internal.telephony.DataConnection.FailCause;
     49 import com.android.internal.util.AsyncChannel;
     50 import com.android.internal.util.Protocol;
     51 
     52 import java.io.FileDescriptor;
     53 import java.io.PrintWriter;
     54 import java.util.ArrayList;
     55 import java.util.HashMap;
     56 import java.util.Map.Entry;
     57 import java.util.Set;
     58 import java.util.concurrent.ConcurrentHashMap;
     59 import java.util.concurrent.atomic.AtomicInteger;
     60 
     61 /**
     62  * {@hide}
     63  */
     64 public abstract class DataConnectionTracker extends Handler {
     65     protected static final boolean DBG = true;
     66     protected static final boolean VDBG = false;
     67 
     68     /**
     69      * IDLE: ready to start data connection setup, default state
     70      * INITING: state of issued setupDefaultPDP() but not finish yet
     71      * CONNECTING: state of issued startPppd() but not finish yet
     72      * SCANNING: data connection fails with one apn but other apns are available
     73      *           ready to start data connection on other apns (before INITING)
     74      * CONNECTED: IP connection is setup
     75      * DISCONNECTING: Connection.disconnect() has been called, but PDP
     76      *                context is not yet deactivated
     77      * FAILED: data connection fail for all apns settings
     78      *
     79      * getDataConnectionState() maps State to DataState
     80      *      FAILED or IDLE : DISCONNECTED
     81      *      INITING or CONNECTING or SCANNING: CONNECTING
     82      *      CONNECTED : CONNECTED or DISCONNECTING
     83      */
     84     public enum State {
     85         IDLE,
     86         INITING,
     87         CONNECTING,
     88         SCANNING,
     89         CONNECTED,
     90         DISCONNECTING,
     91         FAILED
     92     }
     93 
     94     public enum Activity {
     95         NONE,
     96         DATAIN,
     97         DATAOUT,
     98         DATAINANDOUT,
     99         DORMANT
    100     }
    101 
    102     public static String ACTION_DATA_CONNECTION_TRACKER_MESSENGER =
    103         "com.android.internal.telephony";
    104     public static String EXTRA_MESSENGER = "EXTRA_MESSENGER";
    105 
    106     /***** Event Codes *****/
    107     protected static final int BASE = Protocol.BASE_DATA_CONNECTION_TRACKER;
    108     protected static final int EVENT_DATA_SETUP_COMPLETE = BASE + 0;
    109     protected static final int EVENT_RADIO_AVAILABLE = BASE + 1;
    110     protected static final int EVENT_RECORDS_LOADED = BASE + 2;
    111     protected static final int EVENT_TRY_SETUP_DATA = BASE + 3;
    112     protected static final int EVENT_DATA_STATE_CHANGED = BASE + 4;
    113     protected static final int EVENT_POLL_PDP = BASE + 5;
    114     protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = BASE + 6;
    115     protected static final int EVENT_VOICE_CALL_STARTED = BASE + 7;
    116     protected static final int EVENT_VOICE_CALL_ENDED = BASE + 8;
    117     protected static final int EVENT_DATA_CONNECTION_DETACHED = BASE + 9;
    118     protected static final int EVENT_LINK_STATE_CHANGED = BASE + 10;
    119     protected static final int EVENT_ROAMING_ON = BASE + 11;
    120     protected static final int EVENT_ROAMING_OFF = BASE + 12;
    121     protected static final int EVENT_ENABLE_NEW_APN = BASE + 13;
    122     protected static final int EVENT_RESTORE_DEFAULT_APN = BASE + 14;
    123     protected static final int EVENT_DISCONNECT_DONE = BASE + 15;
    124     protected static final int EVENT_DATA_CONNECTION_ATTACHED = BASE + 16;
    125     protected static final int EVENT_DATA_STALL_ALARM = BASE + 17;
    126     protected static final int EVENT_DO_RECOVERY = BASE + 18;
    127     protected static final int EVENT_APN_CHANGED = BASE + 19;
    128     protected static final int EVENT_CDMA_DATA_DETACHED = BASE + 20;
    129     protected static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = BASE + 21;
    130     protected static final int EVENT_PS_RESTRICT_ENABLED = BASE + 22;
    131     protected static final int EVENT_PS_RESTRICT_DISABLED = BASE + 23;
    132     public static final int EVENT_CLEAN_UP_CONNECTION = BASE + 24;
    133     protected static final int EVENT_CDMA_OTA_PROVISION = BASE + 25;
    134     protected static final int EVENT_RESTART_RADIO = BASE + 26;
    135     protected static final int EVENT_SET_INTERNAL_DATA_ENABLE = BASE + 27;
    136     protected static final int EVENT_RESET_DONE = BASE + 28;
    137     public static final int CMD_SET_USER_DATA_ENABLE = BASE + 29;
    138     public static final int EVENT_CLEAN_UP_ALL_CONNECTIONS = BASE + 30;
    139     public static final int CMD_SET_DEPENDENCY_MET = BASE + 31;
    140     public static final int CMD_SET_POLICY_DATA_ENABLE = BASE + 32;
    141 
    142     /***** Constants *****/
    143 
    144     protected static final int APN_INVALID_ID = -1;
    145     protected static final int APN_DEFAULT_ID = 0;
    146     protected static final int APN_MMS_ID = 1;
    147     protected static final int APN_SUPL_ID = 2;
    148     protected static final int APN_DUN_ID = 3;
    149     protected static final int APN_HIPRI_ID = 4;
    150     protected static final int APN_IMS_ID = 5;
    151     protected static final int APN_FOTA_ID = 6;
    152     protected static final int APN_CBS_ID = 7;
    153     protected static final int APN_NUM_TYPES = 8;
    154 
    155     public static final int DISABLED = 0;
    156     public static final int ENABLED = 1;
    157 
    158     public static final String APN_TYPE_KEY = "apnType";
    159 
    160     /** Delay between APN attempts.
    161         Note the property override mechanism is there just for testing purpose only. */
    162     protected static final int APN_DELAY_MILLIS =
    163                                 SystemProperties.getInt("persist.radio.apn_delay", 5000);
    164 
    165     protected Object mDataEnabledLock = new Object();
    166 
    167     // responds to the setInternalDataEnabled call - used internally to turn off data
    168     // for example during emergency calls
    169     protected boolean mInternalDataEnabled = true;
    170 
    171     // responds to public (user) API to enable/disable data use
    172     // independent of mInternalDataEnabled and requests for APN access
    173     // persisted
    174     protected boolean mUserDataEnabled = true;
    175 
    176     // TODO: move away from static state once 5587429 is fixed.
    177     protected static boolean sPolicyDataEnabled = true;
    178 
    179     private boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
    180 
    181     private int enabledCount = 0;
    182 
    183     /* Currently requested APN type (TODO: This should probably be a parameter not a member) */
    184     protected String mRequestedApnType = Phone.APN_TYPE_DEFAULT;
    185 
    186     /** Retry configuration: A doubling of retry times from 5secs to 30minutes */
    187     protected static final String DEFAULT_DATA_RETRY_CONFIG = "default_randomization=2000,"
    188         + "5000,10000,20000,40000,80000:5000,160000:5000,"
    189         + "320000:5000,640000:5000,1280000:5000,1800000:5000";
    190 
    191     /** Retry configuration for secondary networks: 4 tries in 20 sec */
    192     protected static final String SECONDARY_DATA_RETRY_CONFIG =
    193             "max_retries=3, 5000, 5000, 5000";
    194 
    195     /** Slow poll when attempting connection recovery. */
    196     protected static final int POLL_NETSTAT_SLOW_MILLIS = 5000;
    197     /** Default max failure count before attempting to network re-registration. */
    198     protected static final int DEFAULT_MAX_PDP_RESET_FAIL = 3;
    199 
    200     /**
    201      * After detecting a potential connection problem, this is the max number
    202      * of subsequent polls before attempting recovery.
    203      */
    204     protected static final int NO_RECV_POLL_LIMIT = 24;
    205     // 1 sec. default polling interval when screen is on.
    206     protected static final int POLL_NETSTAT_MILLIS = 1000;
    207     // 10 min. default polling interval when screen is off.
    208     protected static final int POLL_NETSTAT_SCREEN_OFF_MILLIS = 1000*60*10;
    209     // 2 min for round trip time
    210     protected static final int POLL_LONGEST_RTT = 120 * 1000;
    211     // Default sent packets without ack which triggers initial recovery steps
    212     protected static final int NUMBER_SENT_PACKETS_OF_HANG = 10;
    213     // how long to wait before switching back to default APN
    214     protected static final int RESTORE_DEFAULT_APN_DELAY = 1 * 60 * 1000;
    215     // system property that can override the above value
    216     protected static final String APN_RESTORE_DELAY_PROP_NAME = "android.telephony.apn-restore";
    217     // represents an invalid IP address
    218     protected static final String NULL_IP = "0.0.0.0";
    219 
    220     // Default for the data stall alarm while non-aggressive stall detection
    221     protected static final int DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS_DEFAULT = 1000 * 60 * 6;
    222     // Default for the data stall alarm for aggressive stall detection
    223     protected static final int DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS_DEFAULT = 1000 * 60;
    224     // If attempt is less than this value we're doing first level recovery
    225     protected static final int DATA_STALL_NO_RECV_POLL_LIMIT = 1;
    226     // Tag for tracking stale alarms
    227     protected static final String DATA_STALL_ALARM_TAG_EXTRA = "data.stall.alram.tag";
    228 
    229     // TODO: See if we can remove INTENT_RECONNECT_ALARM
    230     //       having to have different values for GSM and
    231     //       CDMA. If so we can then remove the need for
    232     //       getActionIntentReconnectAlarm.
    233     protected static final String INTENT_RECONNECT_ALARM_EXTRA_REASON =
    234         "reconnect_alarm_extra_reason";
    235 
    236     // Used for debugging. Send the INTENT with an optional counter value with the number
    237     // of times the setup is to fail before succeeding. If the counter isn't passed the
    238     // setup will fail once. Example fail two times with FailCause.SIGNAL_LOST(-3)
    239     // adb shell am broadcast \
    240     //  -a com.android.internal.telephony.dataconnectiontracker.intent_set_fail_data_setup_counter \
    241     //  --ei fail_data_setup_counter 3 --ei fail_data_setup_fail_cause -3
    242     protected static final String INTENT_SET_FAIL_DATA_SETUP_COUNTER =
    243         "com.android.internal.telephony.dataconnectiontracker.intent_set_fail_data_setup_counter";
    244     protected static final String FAIL_DATA_SETUP_COUNTER = "fail_data_setup_counter";
    245     protected int mFailDataSetupCounter = 0;
    246     protected static final String FAIL_DATA_SETUP_FAIL_CAUSE = "fail_data_setup_fail_cause";
    247     protected FailCause mFailDataSetupFailCause = FailCause.ERROR_UNSPECIFIED;
    248 
    249     protected static final String DEFALUT_DATA_ON_BOOT_PROP = "net.def_data_on_boot";
    250 
    251     // member variables
    252     protected PhoneBase mPhone;
    253     protected Activity mActivity = Activity.NONE;
    254     protected State mState = State.IDLE;
    255     protected Handler mDataConnectionTracker = null;
    256 
    257 
    258     protected long mTxPkts;
    259     protected long mRxPkts;
    260     protected int mNetStatPollPeriod;
    261     protected boolean mNetStatPollEnabled = false;
    262 
    263     protected TxRxSum mDataStallTxRxSum = new TxRxSum(0, 0);
    264     // Used to track stale data stall alarms.
    265     protected int mDataStallAlarmTag = (int) SystemClock.elapsedRealtime();
    266     // The current data stall alarm intent
    267     protected PendingIntent mDataStallAlarmIntent = null;
    268     // Number of packets sent since the last received packet
    269     protected long mSentSinceLastRecv;
    270     // Controls when a simple recovery attempt it to be tried
    271     protected int mNoRecvPollCount = 0;
    272 
    273     // wifi connection status will be updated by sticky intent
    274     protected boolean mIsWifiConnected = false;
    275 
    276     /** Intent sent when the reconnect alarm fires. */
    277     protected PendingIntent mReconnectIntent = null;
    278 
    279     /** CID of active data connection */
    280     protected int mCidActive;
    281 
    282     // When false we will not auto attach and manually attaching is required.
    283     protected boolean mAutoAttachOnCreation = false;
    284 
    285     // State of screen
    286     // (TODO: Reconsider tying directly to screen, maybe this is
    287     //        really a lower power mode")
    288     protected boolean mIsScreenOn = true;
    289 
    290     /** Allows the generation of unique Id's for DataConnection objects */
    291     protected AtomicInteger mUniqueIdGenerator = new AtomicInteger(0);
    292 
    293     /** The data connections. */
    294     protected HashMap<Integer, DataConnection> mDataConnections =
    295         new HashMap<Integer, DataConnection>();
    296 
    297     /** The data connection async channels */
    298     protected HashMap<Integer, DataConnectionAc> mDataConnectionAsyncChannels =
    299         new HashMap<Integer, DataConnectionAc>();
    300 
    301     /** Convert an ApnType string to Id (TODO: Use "enumeration" instead of String for ApnType) */
    302     protected HashMap<String, Integer> mApnToDataConnectionId =
    303                                     new HashMap<String, Integer>();
    304 
    305     /** Phone.APN_TYPE_* ===> ApnContext */
    306     protected ConcurrentHashMap<String, ApnContext> mApnContexts =
    307                                     new ConcurrentHashMap<String, ApnContext>();
    308 
    309     /* Currently active APN */
    310     protected ApnSetting mActiveApn;
    311 
    312     /** allApns holds all apns */
    313     protected ArrayList<ApnSetting> mAllApns = null;
    314 
    315     /** preferred apn */
    316     protected ApnSetting mPreferredApn = null;
    317 
    318     /** Is packet service restricted by network */
    319     protected boolean mIsPsRestricted = false;
    320 
    321     /* Once disposed dont handle any messages */
    322     protected boolean mIsDisposed = false;
    323 
    324     protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver ()
    325     {
    326         @Override
    327         public void onReceive(Context context, Intent intent)
    328         {
    329             String action = intent.getAction();
    330             if (DBG) log("onReceive: action=" + action);
    331             if (action.equals(Intent.ACTION_SCREEN_ON)) {
    332                 mIsScreenOn = true;
    333                 stopNetStatPoll();
    334                 startNetStatPoll();
    335                 restartDataStallAlarm();
    336             } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
    337                 mIsScreenOn = false;
    338                 stopNetStatPoll();
    339                 startNetStatPoll();
    340                 restartDataStallAlarm();
    341             } else if (action.startsWith(getActionIntentReconnectAlarm())) {
    342                 log("Reconnect alarm. Previous state was " + mState);
    343                 onActionIntentReconnectAlarm(intent);
    344             } else if (action.equals(getActionIntentDataStallAlarm())) {
    345                 onActionIntentDataStallAlarm(intent);
    346             } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
    347                 final android.net.NetworkInfo networkInfo = (NetworkInfo)
    348                         intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
    349                 mIsWifiConnected = (networkInfo != null && networkInfo.isConnected());
    350             } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
    351                 final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
    352                         WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
    353 
    354                 if (!enabled) {
    355                     // when WiFi got disabled, the NETWORK_STATE_CHANGED_ACTION
    356                     // quit and won't report disconnected until next enabling.
    357                     mIsWifiConnected = false;
    358                 }
    359             } else if (action.equals(INTENT_SET_FAIL_DATA_SETUP_COUNTER)) {
    360                 mFailDataSetupCounter = intent.getIntExtra(FAIL_DATA_SETUP_COUNTER, 1);
    361                 mFailDataSetupFailCause = FailCause.fromInt(
    362                         intent.getIntExtra(FAIL_DATA_SETUP_FAIL_CAUSE,
    363                                                     FailCause.ERROR_UNSPECIFIED.getErrorCode()));
    364                 if (DBG) log("set mFailDataSetupCounter=" + mFailDataSetupCounter +
    365                         " mFailDataSetupFailCause=" + mFailDataSetupFailCause);
    366             }
    367         }
    368     };
    369 
    370     private final DataRoamingSettingObserver mDataRoamingSettingObserver;
    371 
    372     private class DataRoamingSettingObserver extends ContentObserver {
    373         public DataRoamingSettingObserver(Handler handler) {
    374             super(handler);
    375         }
    376 
    377         public void register(Context context) {
    378             final ContentResolver resolver = context.getContentResolver();
    379             resolver.registerContentObserver(
    380                     Settings.Secure.getUriFor(Settings.Secure.DATA_ROAMING), false, this);
    381         }
    382 
    383         public void unregister(Context context) {
    384             final ContentResolver resolver = context.getContentResolver();
    385             resolver.unregisterContentObserver(this);
    386         }
    387 
    388         @Override
    389         public void onChange(boolean selfChange) {
    390             // already running on mPhone handler thread
    391             handleDataOnRoamingChange();
    392         }
    393     }
    394 
    395     /**
    396      * Maintian the sum of transmit and receive packets.
    397      *
    398      * The packet counts are initizlied and reset to -1 and
    399      * remain -1 until they can be updated.
    400      */
    401     public class TxRxSum {
    402         public long txPkts;
    403         public long rxPkts;
    404 
    405         public TxRxSum() {
    406             reset();
    407         }
    408 
    409         public TxRxSum(long txPkts, long rxPkts) {
    410             this.txPkts = txPkts;
    411             this.rxPkts = rxPkts;
    412         }
    413 
    414         public TxRxSum(TxRxSum sum) {
    415             txPkts = sum.txPkts;
    416             rxPkts = sum.rxPkts;
    417         }
    418 
    419         public void reset() {
    420             txPkts = -1;
    421             rxPkts = -1;
    422         }
    423 
    424         public String toString() {
    425             return "{txSum=" + txPkts + " rxSum=" + rxPkts + "}";
    426         }
    427 
    428         public void updateTxRxSum() {
    429             boolean txUpdated = false, rxUpdated = false;
    430             long txSum = 0, rxSum = 0;
    431             for (ApnContext apnContext : mApnContexts.values()) {
    432                 if (apnContext.getState() == State.CONNECTED) {
    433                     DataConnectionAc dcac = apnContext.getDataConnectionAc();
    434                     if (dcac == null) continue;
    435 
    436                     LinkProperties linkProp = dcac.getLinkPropertiesSync();
    437                     if (linkProp == null) continue;
    438 
    439                     String iface = linkProp.getInterfaceName();
    440 
    441                     if (iface != null) {
    442                         long stats = TrafficStats.getTxPackets(iface);
    443                         if (stats > 0) {
    444                             txUpdated = true;
    445                             txSum += stats;
    446                         }
    447                         stats = TrafficStats.getRxPackets(iface);
    448                         if (stats > 0) {
    449                             rxUpdated = true;
    450                             rxSum += stats;
    451                         }
    452                     }
    453                 }
    454             }
    455             if (txUpdated) this.txPkts = txSum;
    456             if (rxUpdated) this.rxPkts = rxSum;
    457         }
    458     }
    459 
    460     protected boolean isDataSetupCompleteOk(AsyncResult ar) {
    461         if (ar.exception != null) {
    462             if (DBG) log("isDataSetupCompleteOk return false, ar.result=" + ar.result);
    463             return false;
    464         }
    465         if (mFailDataSetupCounter <= 0) {
    466             if (DBG) log("isDataSetupCompleteOk return true");
    467             return true;
    468         }
    469         ar.result = mFailDataSetupFailCause;
    470         if (DBG) {
    471             log("isDataSetupCompleteOk return false" +
    472                     " mFailDataSetupCounter=" + mFailDataSetupCounter +
    473                     " mFailDataSetupFailCause=" + mFailDataSetupFailCause);
    474         }
    475         mFailDataSetupCounter -= 1;
    476         return false;
    477     }
    478 
    479     protected void onActionIntentReconnectAlarm(Intent intent) {
    480         String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
    481         if (mState == State.FAILED) {
    482             Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
    483             msg.arg1 = 0; // tearDown is false
    484             msg.arg2 = 0;
    485             msg.obj = reason;
    486             sendMessage(msg);
    487         }
    488         sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
    489     }
    490 
    491     protected void onActionIntentDataStallAlarm(Intent intent) {
    492         if (VDBG) log("onActionIntentDataStallAlarm: action=" + intent.getAction());
    493         Message msg = obtainMessage(EVENT_DATA_STALL_ALARM, intent.getAction());
    494         msg.arg1 = intent.getIntExtra(DATA_STALL_ALARM_TAG_EXTRA, 0);
    495         sendMessage(msg);
    496     }
    497 
    498     /**
    499      * Default constructor
    500      */
    501     protected DataConnectionTracker(PhoneBase phone) {
    502         super();
    503         if (DBG) log("DCT.constructor");
    504         mPhone = phone;
    505 
    506         IntentFilter filter = new IntentFilter();
    507         filter.addAction(getActionIntentReconnectAlarm());
    508         filter.addAction(Intent.ACTION_SCREEN_ON);
    509         filter.addAction(Intent.ACTION_SCREEN_OFF);
    510         filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
    511         filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
    512         filter.addAction(INTENT_SET_FAIL_DATA_SETUP_COUNTER);
    513 
    514         mUserDataEnabled = Settings.Secure.getInt(
    515                 mPhone.getContext().getContentResolver(), Settings.Secure.MOBILE_DATA, 1) == 1;
    516 
    517         // TODO: Why is this registering the phone as the receiver of the intent
    518         //       and not its own handler?
    519         mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
    520 
    521         // This preference tells us 1) initial condition for "dataEnabled",
    522         // and 2) whether the RIL will setup the baseband to auto-PS attach.
    523 
    524         dataEnabled[APN_DEFAULT_ID] = SystemProperties.getBoolean(DEFALUT_DATA_ON_BOOT_PROP,
    525                                                                   true);
    526         if (dataEnabled[APN_DEFAULT_ID]) {
    527             enabledCount++;
    528         }
    529 
    530         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
    531         mAutoAttachOnCreation = sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false);
    532 
    533         // watch for changes to Settings.Secure.DATA_ROAMING
    534         mDataRoamingSettingObserver = new DataRoamingSettingObserver(mPhone);
    535         mDataRoamingSettingObserver.register(mPhone.getContext());
    536     }
    537 
    538     public void dispose() {
    539         if (DBG) log("DCT.dispose");
    540         for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
    541             dcac.disconnect();
    542         }
    543         mDataConnectionAsyncChannels.clear();
    544         mIsDisposed = true;
    545         mPhone.getContext().unregisterReceiver(this.mIntentReceiver);
    546         mDataRoamingSettingObserver.unregister(mPhone.getContext());
    547     }
    548 
    549     protected void broadcastMessenger() {
    550         Intent intent = new Intent(ACTION_DATA_CONNECTION_TRACKER_MESSENGER);
    551         intent.putExtra(EXTRA_MESSENGER, new Messenger(this));
    552         mPhone.getContext().sendBroadcast(intent);
    553     }
    554 
    555     public Activity getActivity() {
    556         return mActivity;
    557     }
    558 
    559     public boolean isApnTypeActive(String type) {
    560         // TODO: support simultaneous with List instead
    561         if (Phone.APN_TYPE_DUN.equals(type)) {
    562             ApnSetting dunApn = fetchDunApn();
    563             if (dunApn != null) {
    564                 return ((mActiveApn != null) && (dunApn.toString().equals(mActiveApn.toString())));
    565             }
    566         }
    567         return mActiveApn != null && mActiveApn.canHandleType(type);
    568     }
    569 
    570     protected ApnSetting fetchDunApn() {
    571         if (SystemProperties.getBoolean("net.tethering.noprovisioning", false)) {
    572             log("fetchDunApn: net.tethering.noprovisioning=true ret: null");
    573             return null;
    574         }
    575         Context c = mPhone.getContext();
    576         String apnData = Settings.Secure.getString(c.getContentResolver(),
    577                 Settings.Secure.TETHER_DUN_APN);
    578         ApnSetting dunSetting = ApnSetting.fromString(apnData);
    579         if (dunSetting != null) {
    580             if (VDBG) log("fetchDunApn: secure TETHER_DUN_APN dunSetting=" + dunSetting);
    581             return dunSetting;
    582         }
    583 
    584         apnData = c.getResources().getString(R.string.config_tether_apndata);
    585         dunSetting = ApnSetting.fromString(apnData);
    586         if (VDBG) log("fetchDunApn: config_tether_apndata dunSetting=" + dunSetting);
    587         return dunSetting;
    588     }
    589 
    590     public String[] getActiveApnTypes() {
    591         String[] result;
    592         if (mActiveApn != null) {
    593             result = mActiveApn.types;
    594         } else {
    595             result = new String[1];
    596             result[0] = Phone.APN_TYPE_DEFAULT;
    597         }
    598         return result;
    599     }
    600 
    601     /** TODO: See if we can remove */
    602     public String getActiveApnString(String apnType) {
    603         String result = null;
    604         if (mActiveApn != null) {
    605             result = mActiveApn.apn;
    606         }
    607         return result;
    608     }
    609 
    610     /**
    611      * Modify {@link Settings.Secure#DATA_ROAMING} value.
    612      */
    613     public void setDataOnRoamingEnabled(boolean enabled) {
    614         if (getDataOnRoamingEnabled() != enabled) {
    615             final ContentResolver resolver = mPhone.getContext().getContentResolver();
    616             Settings.Secure.putInt(resolver, Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
    617             // will trigger handleDataOnRoamingChange() through observer
    618         }
    619     }
    620 
    621     /**
    622      * Return current {@link Settings.Secure#DATA_ROAMING} value.
    623      */
    624     public boolean getDataOnRoamingEnabled() {
    625         try {
    626             final ContentResolver resolver = mPhone.getContext().getContentResolver();
    627             return Settings.Secure.getInt(resolver, Settings.Secure.DATA_ROAMING) != 0;
    628         } catch (SettingNotFoundException snfe) {
    629             return false;
    630         }
    631     }
    632 
    633     private void handleDataOnRoamingChange() {
    634         if (mPhone.getServiceState().getRoaming()) {
    635             if (getDataOnRoamingEnabled()) {
    636                 resetAllRetryCounts();
    637             }
    638             sendMessage(obtainMessage(EVENT_ROAMING_ON));
    639         }
    640     }
    641 
    642     // abstract methods
    643     protected abstract String getActionIntentReconnectAlarm();
    644     protected abstract String getActionIntentDataStallAlarm();
    645     protected abstract void startNetStatPoll();
    646     protected abstract void stopNetStatPoll();
    647     protected abstract void restartDataStallAlarm();
    648     protected abstract void restartRadio();
    649     protected abstract void log(String s);
    650     protected abstract void loge(String s);
    651     protected abstract boolean isDataAllowed();
    652     protected abstract boolean isApnTypeAvailable(String type);
    653     public    abstract State getState(String apnType);
    654     protected abstract void setState(State s);
    655     protected abstract void gotoIdleAndNotifyDataConnection(String reason);
    656 
    657     protected abstract boolean onTrySetupData(String reason);
    658     protected abstract void onRoamingOff();
    659     protected abstract void onRoamingOn();
    660     protected abstract void onRadioAvailable();
    661     protected abstract void onRadioOffOrNotAvailable();
    662     protected abstract void onDataSetupComplete(AsyncResult ar);
    663     protected abstract void onDisconnectDone(int connId, AsyncResult ar);
    664     protected abstract void onVoiceCallStarted();
    665     protected abstract void onVoiceCallEnded();
    666     protected abstract void onCleanUpConnection(boolean tearDown, int apnId, String reason);
    667     protected abstract void onCleanUpAllConnections(String cause);
    668     protected abstract boolean isDataPossible(String apnType);
    669 
    670     protected void onDataStallAlarm(int tag) {
    671         loge("onDataStallAlarm: not impleted tag=" + tag);
    672     }
    673 
    674     @Override
    675     public void handleMessage(Message msg) {
    676         switch (msg.what) {
    677             case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
    678                 log("DISCONNECTED_CONNECTED: msg=" + msg);
    679                 DataConnectionAc dcac = (DataConnectionAc) msg.obj;
    680                 mDataConnectionAsyncChannels.remove(dcac.dataConnection.getDataConnectionId());
    681                 dcac.disconnected();
    682                 break;
    683             }
    684             case EVENT_ENABLE_NEW_APN:
    685                 onEnableApn(msg.arg1, msg.arg2);
    686                 break;
    687 
    688             case EVENT_TRY_SETUP_DATA:
    689                 String reason = null;
    690                 if (msg.obj instanceof String) {
    691                     reason = (String) msg.obj;
    692                 }
    693                 onTrySetupData(reason);
    694                 break;
    695 
    696             case EVENT_DATA_STALL_ALARM:
    697                 onDataStallAlarm(msg.arg1);
    698                 break;
    699 
    700             case EVENT_ROAMING_OFF:
    701                 if (getDataOnRoamingEnabled() == false) {
    702                     resetAllRetryCounts();
    703                 }
    704                 onRoamingOff();
    705                 break;
    706 
    707             case EVENT_ROAMING_ON:
    708                 onRoamingOn();
    709                 break;
    710 
    711             case EVENT_RADIO_AVAILABLE:
    712                 onRadioAvailable();
    713                 break;
    714 
    715             case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
    716                 onRadioOffOrNotAvailable();
    717                 break;
    718 
    719             case EVENT_DATA_SETUP_COMPLETE:
    720                 mCidActive = msg.arg1;
    721                 onDataSetupComplete((AsyncResult) msg.obj);
    722                 break;
    723 
    724             case EVENT_DISCONNECT_DONE:
    725                 log("DataConnectoinTracker.handleMessage: EVENT_DISCONNECT_DONE msg=" + msg);
    726                 onDisconnectDone(msg.arg1, (AsyncResult) msg.obj);
    727                 break;
    728 
    729             case EVENT_VOICE_CALL_STARTED:
    730                 onVoiceCallStarted();
    731                 break;
    732 
    733             case EVENT_VOICE_CALL_ENDED:
    734                 onVoiceCallEnded();
    735                 break;
    736 
    737             case EVENT_CLEAN_UP_ALL_CONNECTIONS: {
    738                 onCleanUpAllConnections((String) msg.obj);
    739                 break;
    740             }
    741             case EVENT_CLEAN_UP_CONNECTION: {
    742                 boolean tearDown = (msg.arg1 == 0) ? false : true;
    743                 onCleanUpConnection(tearDown, msg.arg2, (String) msg.obj);
    744                 break;
    745             }
    746             case EVENT_SET_INTERNAL_DATA_ENABLE: {
    747                 boolean enabled = (msg.arg1 == ENABLED) ? true : false;
    748                 onSetInternalDataEnabled(enabled);
    749                 break;
    750             }
    751             case EVENT_RESET_DONE: {
    752                 if (DBG) log("EVENT_RESET_DONE");
    753                 onResetDone((AsyncResult) msg.obj);
    754                 break;
    755             }
    756             case CMD_SET_USER_DATA_ENABLE: {
    757                 final boolean enabled = (msg.arg1 == ENABLED) ? true : false;
    758                 if (DBG) log("CMD_SET_USER_DATA_ENABLE enabled=" + enabled);
    759                 onSetUserDataEnabled(enabled);
    760                 break;
    761             }
    762             case CMD_SET_DEPENDENCY_MET: {
    763                 boolean met = (msg.arg1 == ENABLED) ? true : false;
    764                 if (DBG) log("CMD_SET_DEPENDENCY_MET met=" + met);
    765                 Bundle bundle = msg.getData();
    766                 if (bundle != null) {
    767                     String apnType = (String)bundle.get(APN_TYPE_KEY);
    768                     if (apnType != null) {
    769                         onSetDependencyMet(apnType, met);
    770                     }
    771                 }
    772                 break;
    773             }
    774             case CMD_SET_POLICY_DATA_ENABLE: {
    775                 final boolean enabled = (msg.arg1 == ENABLED) ? true : false;
    776                 onSetPolicyDataEnabled(enabled);
    777                 break;
    778             }
    779             default:
    780                 Log.e("DATA", "Unidentified event msg=" + msg);
    781                 break;
    782         }
    783     }
    784 
    785     /**
    786      * Report on whether data connectivity is enabled
    787      *
    788      * @return {@code false} if data connectivity has been explicitly disabled,
    789      *         {@code true} otherwise.
    790      */
    791     public boolean getAnyDataEnabled() {
    792         final boolean result;
    793         synchronized (mDataEnabledLock) {
    794             result = (mInternalDataEnabled && mUserDataEnabled && sPolicyDataEnabled
    795                     && (enabledCount != 0));
    796         }
    797         if (!result && DBG) log("getAnyDataEnabled " + result);
    798         return result;
    799     }
    800 
    801     protected boolean isEmergency() {
    802         final boolean result;
    803         synchronized (mDataEnabledLock) {
    804             result = mPhone.isInEcm() || mPhone.isInEmergencyCall();
    805         }
    806         log("isEmergency: result=" + result);
    807         return result;
    808     }
    809 
    810     protected int apnTypeToId(String type) {
    811         if (TextUtils.equals(type, Phone.APN_TYPE_DEFAULT)) {
    812             return APN_DEFAULT_ID;
    813         } else if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
    814             return APN_MMS_ID;
    815         } else if (TextUtils.equals(type, Phone.APN_TYPE_SUPL)) {
    816             return APN_SUPL_ID;
    817         } else if (TextUtils.equals(type, Phone.APN_TYPE_DUN)) {
    818             return APN_DUN_ID;
    819         } else if (TextUtils.equals(type, Phone.APN_TYPE_HIPRI)) {
    820             return APN_HIPRI_ID;
    821         } else if (TextUtils.equals(type, Phone.APN_TYPE_IMS)) {
    822             return APN_IMS_ID;
    823         } else if (TextUtils.equals(type, Phone.APN_TYPE_FOTA)) {
    824             return APN_FOTA_ID;
    825         } else if (TextUtils.equals(type, Phone.APN_TYPE_CBS)) {
    826             return APN_CBS_ID;
    827         } else {
    828             return APN_INVALID_ID;
    829         }
    830     }
    831 
    832     protected String apnIdToType(int id) {
    833         switch (id) {
    834         case APN_DEFAULT_ID:
    835             return Phone.APN_TYPE_DEFAULT;
    836         case APN_MMS_ID:
    837             return Phone.APN_TYPE_MMS;
    838         case APN_SUPL_ID:
    839             return Phone.APN_TYPE_SUPL;
    840         case APN_DUN_ID:
    841             return Phone.APN_TYPE_DUN;
    842         case APN_HIPRI_ID:
    843             return Phone.APN_TYPE_HIPRI;
    844         case APN_IMS_ID:
    845             return Phone.APN_TYPE_IMS;
    846         case APN_FOTA_ID:
    847             return Phone.APN_TYPE_FOTA;
    848         case APN_CBS_ID:
    849             return Phone.APN_TYPE_CBS;
    850         default:
    851             log("Unknown id (" + id + ") in apnIdToType");
    852             return Phone.APN_TYPE_DEFAULT;
    853         }
    854     }
    855 
    856     protected LinkProperties getLinkProperties(String apnType) {
    857         int id = apnTypeToId(apnType);
    858 
    859         if (isApnIdEnabled(id)) {
    860             // TODO - remove this cdma-only hack and support multiple DCs.
    861             DataConnectionAc dcac = mDataConnectionAsyncChannels.get(0);
    862             return dcac.getLinkPropertiesSync();
    863         } else {
    864             return new LinkProperties();
    865         }
    866     }
    867 
    868     protected LinkCapabilities getLinkCapabilities(String apnType) {
    869         int id = apnTypeToId(apnType);
    870         if (isApnIdEnabled(id)) {
    871             // TODO - remove this cdma-only hack and support multiple DCs.
    872             DataConnectionAc dcac = mDataConnectionAsyncChannels.get(0);
    873             return dcac.getLinkCapabilitiesSync();
    874         } else {
    875             return new LinkCapabilities();
    876         }
    877     }
    878 
    879     // tell all active apns of the current condition
    880     protected void notifyDataConnection(String reason) {
    881         for (int id = 0; id < APN_NUM_TYPES; id++) {
    882             if (dataEnabled[id]) {
    883                 mPhone.notifyDataConnection(reason, apnIdToType(id));
    884             }
    885         }
    886         notifyOffApnsOfAvailability(reason);
    887     }
    888 
    889     // a new APN has gone active and needs to send events to catch up with the
    890     // current condition
    891     private void notifyApnIdUpToCurrent(String reason, int apnId) {
    892         switch (mState) {
    893             case IDLE:
    894             case INITING:
    895                 break;
    896             case CONNECTING:
    897             case SCANNING:
    898                 mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTING);
    899                 break;
    900             case CONNECTED:
    901             case DISCONNECTING:
    902                 mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTING);
    903                 mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTED);
    904                 break;
    905         }
    906     }
    907 
    908     // since we normally don't send info to a disconnected APN, we need to do this specially
    909     private void notifyApnIdDisconnected(String reason, int apnId) {
    910         mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.DISCONNECTED);
    911     }
    912 
    913     // disabled apn's still need avail/unavail notificiations - send them out
    914     protected void notifyOffApnsOfAvailability(String reason) {
    915         if (DBG) log("notifyOffApnsOfAvailability - reason= " + reason);
    916         for (int id = 0; id < APN_NUM_TYPES; id++) {
    917             if (!isApnIdEnabled(id)) {
    918                 notifyApnIdDisconnected(reason, id);
    919             }
    920         }
    921     }
    922 
    923     public boolean isApnTypeEnabled(String apnType) {
    924         if (apnType == null) {
    925             return false;
    926         } else {
    927             return isApnIdEnabled(apnTypeToId(apnType));
    928         }
    929     }
    930 
    931     protected synchronized boolean isApnIdEnabled(int id) {
    932         if (id != APN_INVALID_ID) {
    933             return dataEnabled[id];
    934         }
    935         return false;
    936     }
    937 
    938     /**
    939      * Ensure that we are connected to an APN of the specified type.
    940      *
    941      * @param type the APN type (currently the only valid values are
    942      *            {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL})
    943      * @return Success is indicated by {@code Phone.APN_ALREADY_ACTIVE} or
    944      *         {@code Phone.APN_REQUEST_STARTED}. In the latter case, a
    945      *         broadcast will be sent by the ConnectivityManager when a
    946      *         connection to the APN has been established.
    947      */
    948     public synchronized int enableApnType(String type) {
    949         int id = apnTypeToId(type);
    950         if (id == APN_INVALID_ID) {
    951             return Phone.APN_REQUEST_FAILED;
    952         }
    953 
    954         if (DBG) {
    955             log("enableApnType(" + type + "), isApnTypeActive = " + isApnTypeActive(type)
    956                     + ", isApnIdEnabled =" + isApnIdEnabled(id) + " and state = " + mState);
    957         }
    958 
    959         if (!isApnTypeAvailable(type)) {
    960             if (DBG) log("type not available");
    961             return Phone.APN_TYPE_NOT_AVAILABLE;
    962         }
    963 
    964         if (isApnIdEnabled(id)) {
    965             return Phone.APN_ALREADY_ACTIVE;
    966         } else {
    967             setEnabled(id, true);
    968         }
    969         return Phone.APN_REQUEST_STARTED;
    970     }
    971 
    972     /**
    973      * The APN of the specified type is no longer needed. Ensure that if use of
    974      * the default APN has not been explicitly disabled, we are connected to the
    975      * default APN.
    976      *
    977      * @param type the APN type. The only valid values are currently
    978      *            {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}.
    979      * @return Success is indicated by {@code Phone.APN_ALREADY_ACTIVE} or
    980      *         {@code Phone.APN_REQUEST_STARTED}. In the latter case, a
    981      *         broadcast will be sent by the ConnectivityManager when a
    982      *         connection to the APN has been disconnected. A {@code
    983      *         Phone.APN_REQUEST_FAILED} is returned if the type parameter is
    984      *         invalid or if the apn wasn't enabled.
    985      */
    986     public synchronized int disableApnType(String type) {
    987         if (DBG) log("disableApnType(" + type + ")");
    988         int id = apnTypeToId(type);
    989         if (id == APN_INVALID_ID) {
    990             return Phone.APN_REQUEST_FAILED;
    991         }
    992         if (isApnIdEnabled(id)) {
    993             setEnabled(id, false);
    994             if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
    995                 if (dataEnabled[APN_DEFAULT_ID]) {
    996                     return Phone.APN_ALREADY_ACTIVE;
    997                 } else {
    998                     return Phone.APN_REQUEST_STARTED;
    999                 }
   1000             } else {
   1001                 return Phone.APN_REQUEST_STARTED;
   1002             }
   1003         } else {
   1004             return Phone.APN_REQUEST_FAILED;
   1005         }
   1006     }
   1007 
   1008     protected void setEnabled(int id, boolean enable) {
   1009         if (DBG) {
   1010             log("setEnabled(" + id + ", " + enable + ") with old state = " + dataEnabled[id]
   1011                     + " and enabledCount = " + enabledCount);
   1012         }
   1013         Message msg = obtainMessage(EVENT_ENABLE_NEW_APN);
   1014         msg.arg1 = id;
   1015         msg.arg2 = (enable ? ENABLED : DISABLED);
   1016         sendMessage(msg);
   1017     }
   1018 
   1019     protected void onEnableApn(int apnId, int enabled) {
   1020         if (DBG) {
   1021             log("EVENT_APN_ENABLE_REQUEST apnId=" + apnId + ", apnType=" + apnIdToType(apnId) +
   1022                     ", enabled=" + enabled + ", dataEnabled = " + dataEnabled[apnId] +
   1023                     ", enabledCount = " + enabledCount + ", isApnTypeActive = " +
   1024                     isApnTypeActive(apnIdToType(apnId)));
   1025         }
   1026         if (enabled == ENABLED) {
   1027             synchronized (this) {
   1028                 if (!dataEnabled[apnId]) {
   1029                     dataEnabled[apnId] = true;
   1030                     enabledCount++;
   1031                 }
   1032             }
   1033             String type = apnIdToType(apnId);
   1034             if (!isApnTypeActive(type)) {
   1035                 mRequestedApnType = type;
   1036                 onEnableNewApn();
   1037             } else {
   1038                 notifyApnIdUpToCurrent(Phone.REASON_APN_SWITCHED, apnId);
   1039             }
   1040         } else {
   1041             // disable
   1042             boolean didDisable = false;
   1043             synchronized (this) {
   1044                 if (dataEnabled[apnId]) {
   1045                     dataEnabled[apnId] = false;
   1046                     enabledCount--;
   1047                     didDisable = true;
   1048                 }
   1049             }
   1050             if (didDisable) {
   1051                 if ((enabledCount == 0) || (apnId == APN_DUN_ID)) {
   1052                     mRequestedApnType = Phone.APN_TYPE_DEFAULT;
   1053                     onCleanUpConnection(true, apnId, Phone.REASON_DATA_DISABLED);
   1054                 }
   1055 
   1056                 // send the disconnect msg manually, since the normal route wont send
   1057                 // it (it's not enabled)
   1058                 notifyApnIdDisconnected(Phone.REASON_DATA_DISABLED, apnId);
   1059                 if (dataEnabled[APN_DEFAULT_ID] == true
   1060                         && !isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
   1061                     // TODO - this is an ugly way to restore the default conn - should be done
   1062                     // by a real contention manager and policy that disconnects the lower pri
   1063                     // stuff as enable requests come in and pops them back on as we disable back
   1064                     // down to the lower pri stuff
   1065                     mRequestedApnType = Phone.APN_TYPE_DEFAULT;
   1066                     onEnableNewApn();
   1067                 }
   1068             }
   1069         }
   1070     }
   1071 
   1072     /**
   1073      * Called when we switch APNs.
   1074      *
   1075      * mRequestedApnType is set prior to call
   1076      * To be overridden.
   1077      */
   1078     protected void onEnableNewApn() {
   1079     }
   1080 
   1081     /**
   1082      * Called when EVENT_RESET_DONE is received so goto
   1083      * IDLE state and send notifications to those interested.
   1084      *
   1085      * TODO - currently unused.  Needs to be hooked into DataConnection cleanup
   1086      * TODO - needs to pass some notion of which connection is reset..
   1087      */
   1088     protected void onResetDone(AsyncResult ar) {
   1089         if (DBG) log("EVENT_RESET_DONE");
   1090         String reason = null;
   1091         if (ar.userObj instanceof String) {
   1092             reason = (String) ar.userObj;
   1093         }
   1094         gotoIdleAndNotifyDataConnection(reason);
   1095     }
   1096 
   1097     /**
   1098      * Prevent mobile data connections from being established, or once again
   1099      * allow mobile data connections. If the state toggles, then either tear
   1100      * down or set up data, as appropriate to match the new state.
   1101      *
   1102      * @param enable indicates whether to enable ({@code true}) or disable (
   1103      *            {@code false}) data
   1104      * @return {@code true} if the operation succeeded
   1105      */
   1106     public boolean setInternalDataEnabled(boolean enable) {
   1107         if (DBG)
   1108             log("setInternalDataEnabled(" + enable + ")");
   1109 
   1110         Message msg = obtainMessage(EVENT_SET_INTERNAL_DATA_ENABLE);
   1111         msg.arg1 = (enable ? ENABLED : DISABLED);
   1112         sendMessage(msg);
   1113         return true;
   1114     }
   1115 
   1116     protected void onSetInternalDataEnabled(boolean enabled) {
   1117         synchronized (mDataEnabledLock) {
   1118             mInternalDataEnabled = enabled;
   1119             if (enabled) {
   1120                 log("onSetInternalDataEnabled: changed to enabled, try to setup data call");
   1121                 resetAllRetryCounts();
   1122                 onTrySetupData(Phone.REASON_DATA_ENABLED);
   1123             } else {
   1124                 log("onSetInternalDataEnabled: changed to disabled, cleanUpAllConnections");
   1125                 cleanUpAllConnections(null);
   1126             }
   1127         }
   1128     }
   1129 
   1130     public void cleanUpAllConnections(String cause) {
   1131         Message msg = obtainMessage(EVENT_CLEAN_UP_ALL_CONNECTIONS);
   1132         msg.obj = cause;
   1133         sendMessage(msg);
   1134     }
   1135 
   1136     public abstract boolean isDisconnected();
   1137 
   1138     protected void onSetUserDataEnabled(boolean enabled) {
   1139         synchronized (mDataEnabledLock) {
   1140             final boolean prevEnabled = getAnyDataEnabled();
   1141             if (mUserDataEnabled != enabled) {
   1142                 mUserDataEnabled = enabled;
   1143                 Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
   1144                         Settings.Secure.MOBILE_DATA, enabled ? 1 : 0);
   1145                 if (getDataOnRoamingEnabled() == false &&
   1146                         mPhone.getServiceState().getRoaming() == true) {
   1147                     if (enabled) {
   1148                         notifyOffApnsOfAvailability(Phone.REASON_ROAMING_ON);
   1149                     } else {
   1150                         notifyOffApnsOfAvailability(Phone.REASON_DATA_DISABLED);
   1151                     }
   1152                 }
   1153                 if (prevEnabled != getAnyDataEnabled()) {
   1154                     if (!prevEnabled) {
   1155                         resetAllRetryCounts();
   1156                         onTrySetupData(Phone.REASON_DATA_ENABLED);
   1157                     } else {
   1158                         onCleanUpAllConnections(Phone.REASON_DATA_DISABLED);
   1159                     }
   1160                 }
   1161             }
   1162         }
   1163     }
   1164 
   1165     protected void onSetDependencyMet(String apnType, boolean met) {
   1166     }
   1167 
   1168     protected void onSetPolicyDataEnabled(boolean enabled) {
   1169         synchronized (mDataEnabledLock) {
   1170             final boolean prevEnabled = getAnyDataEnabled();
   1171             if (sPolicyDataEnabled != enabled) {
   1172                 sPolicyDataEnabled = enabled;
   1173                 if (prevEnabled != getAnyDataEnabled()) {
   1174                     if (!prevEnabled) {
   1175                         resetAllRetryCounts();
   1176                         onTrySetupData(Phone.REASON_DATA_ENABLED);
   1177                     } else {
   1178                         onCleanUpAllConnections(Phone.REASON_DATA_DISABLED);
   1179                     }
   1180                 }
   1181             }
   1182         }
   1183     }
   1184 
   1185     protected String getReryConfig(boolean forDefault) {
   1186         int nt = mPhone.getServiceState().getNetworkType();
   1187 
   1188         if ((nt == TelephonyManager.NETWORK_TYPE_CDMA) ||
   1189             (nt == TelephonyManager.NETWORK_TYPE_1xRTT) ||
   1190             (nt == TelephonyManager.NETWORK_TYPE_EVDO_0) ||
   1191             (nt == TelephonyManager.NETWORK_TYPE_EVDO_A) ||
   1192             (nt == TelephonyManager.NETWORK_TYPE_EVDO_B) ||
   1193             (nt == TelephonyManager.NETWORK_TYPE_EHRPD)) {
   1194             // CDMA variant
   1195             return SystemProperties.get("ro.cdma.data_retry_config");
   1196         } else {
   1197             // Use GSM varient for all others.
   1198             if (forDefault) {
   1199                 return SystemProperties.get("ro.gsm.data_retry_config");
   1200             } else {
   1201                 return SystemProperties.get("ro.gsm.2nd_data_retry_config");
   1202             }
   1203         }
   1204     }
   1205 
   1206     protected void resetAllRetryCounts() {
   1207         for (ApnContext ac : mApnContexts.values()) {
   1208             ac.setRetryCount(0);
   1209         }
   1210         for (DataConnection dc : mDataConnections.values()) {
   1211             dc.resetRetryCount();
   1212         }
   1213     }
   1214 
   1215     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   1216         pw.println("DataConnectionTracker:");
   1217         pw.println(" mInternalDataEnabled=" + mInternalDataEnabled);
   1218         pw.println(" mUserDataEnabled=" + mUserDataEnabled);
   1219         pw.println(" sPolicyDataEnabed=" + sPolicyDataEnabled);
   1220         pw.println(" dataEnabled:");
   1221         for(int i=0; i < dataEnabled.length; i++) {
   1222             pw.printf("  dataEnabled[%d]=%b\n", i, dataEnabled[i]);
   1223         }
   1224         pw.flush();
   1225         pw.println(" enabledCount=" + enabledCount);
   1226         pw.println(" mRequestedApnType=" + mRequestedApnType);
   1227         pw.println(" mPhone=" + mPhone.getPhoneName());
   1228         pw.println(" mActivity=" + mActivity);
   1229         pw.println(" mState=" + mState);
   1230         pw.println(" mTxPkts=" + mTxPkts);
   1231         pw.println(" mRxPkts=" + mRxPkts);
   1232         pw.println(" mNetStatPollPeriod=" + mNetStatPollPeriod);
   1233         pw.println(" mNetStatPollEnabled=" + mNetStatPollEnabled);
   1234         pw.println(" mDataStallTxRxSum=" + mDataStallTxRxSum);
   1235         pw.println(" mDataStallAlarmTag=" + mDataStallAlarmTag);
   1236         pw.println(" mSentSinceLastRecv=" + mSentSinceLastRecv);
   1237         pw.println(" mNoRecvPollCount=" + mNoRecvPollCount);
   1238         pw.println(" mIsWifiConnected=" + mIsWifiConnected);
   1239         pw.println(" mReconnectIntent=" + mReconnectIntent);
   1240         pw.println(" mCidActive=" + mCidActive);
   1241         pw.println(" mAutoAttachOnCreation=" + mAutoAttachOnCreation);
   1242         pw.println(" mIsScreenOn=" + mIsScreenOn);
   1243         pw.println(" mUniqueIdGenerator=" + mUniqueIdGenerator);
   1244         pw.flush();
   1245         pw.println(" ***************************************");
   1246         Set<Entry<Integer, DataConnection> > mDcSet = mDataConnections.entrySet();
   1247         pw.println(" mDataConnections: count=" + mDcSet.size());
   1248         for (Entry<Integer, DataConnection> entry : mDcSet) {
   1249             pw.printf(" *** mDataConnection[%d] \n", entry.getKey());
   1250             entry.getValue().dump(fd, pw, args);
   1251         }
   1252         pw.println(" ***************************************");
   1253         pw.flush();
   1254         Set<Entry<String, Integer>> mApnToDcIdSet = mApnToDataConnectionId.entrySet();
   1255         pw.println(" mApnToDataConnectonId size=" + mApnToDcIdSet.size());
   1256         for (Entry<String, Integer> entry : mApnToDcIdSet) {
   1257             pw.printf(" mApnToDataConnectonId[%s]=%d\n", entry.getKey(), entry.getValue());
   1258         }
   1259         pw.println(" ***************************************");
   1260         pw.flush();
   1261         if (mApnContexts != null) {
   1262             Set<Entry<String, ApnContext>> mApnContextsSet = mApnContexts.entrySet();
   1263             pw.println(" mApnContexts size=" + mApnContextsSet.size());
   1264             for (Entry<String, ApnContext> entry : mApnContextsSet) {
   1265                 entry.getValue().dump(fd, pw, args);
   1266             }
   1267             pw.println(" ***************************************");
   1268         } else {
   1269             pw.println(" mApnContexts=null");
   1270         }
   1271         pw.flush();
   1272         pw.println(" mActiveApn=" + mActiveApn);
   1273         if (mAllApns != null) {
   1274             pw.println(" mAllApns size=" + mAllApns.size());
   1275             for (int i=0; i < mAllApns.size(); i++) {
   1276                 pw.printf(" mAllApns[%d]: %s\n", i, mAllApns.get(i));
   1277             }
   1278             pw.flush();
   1279         } else {
   1280             pw.println(" mAllApns=null");
   1281         }
   1282         pw.println(" mPreferredApn=" + mPreferredApn);
   1283         pw.println(" mIsPsRestricted=" + mIsPsRestricted);
   1284         pw.println(" mIsDisposed=" + mIsDisposed);
   1285         pw.println(" mIntentReceiver=" + mIntentReceiver);
   1286         pw.println(" mDataRoamingSettingObserver=" + mDataRoamingSettingObserver);
   1287         pw.flush();
   1288     }
   1289 }
   1290