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 
    308     /* Currently active APN */
    309     protected ApnSetting mActiveApn;
    310 
    311     /** allApns holds all apns */
    312     protected ArrayList<ApnSetting> mAllApns = null;
    313 
    314     /** preferred apn */
    315     protected ApnSetting mPreferredApn = null;
    316 
    317     /** Is packet service restricted by network */
    318     protected boolean mIsPsRestricted = false;
    319 
    320     /* Once disposed dont handle any messages */
    321     protected boolean mIsDisposed = false;
    322 
    323     protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver ()
    324     {
    325         @Override
    326         public void onReceive(Context context, Intent intent)
    327         {
    328             String action = intent.getAction();
    329             if (DBG) log("onReceive: action=" + action);
    330             if (action.equals(Intent.ACTION_SCREEN_ON)) {
    331                 mIsScreenOn = true;
    332                 stopNetStatPoll();
    333                 startNetStatPoll();
    334                 restartDataStallAlarm();
    335             } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
    336                 mIsScreenOn = false;
    337                 stopNetStatPoll();
    338                 startNetStatPoll();
    339                 restartDataStallAlarm();
    340             } else if (action.startsWith(getActionIntentReconnectAlarm())) {
    341                 log("Reconnect alarm. Previous state was " + mState);
    342                 onActionIntentReconnectAlarm(intent);
    343             } else if (action.equals(getActionIntentDataStallAlarm())) {
    344                 onActionIntentDataStallAlarm(intent);
    345             } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
    346                 final android.net.NetworkInfo networkInfo = (NetworkInfo)
    347                         intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
    348                 mIsWifiConnected = (networkInfo != null && networkInfo.isConnected());
    349             } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
    350                 final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
    351                         WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
    352 
    353                 if (!enabled) {
    354                     // when WiFi got disabled, the NETWORK_STATE_CHANGED_ACTION
    355                     // quit and won't report disconnected until next enabling.
    356                     mIsWifiConnected = false;
    357                 }
    358             } else if (action.equals(INTENT_SET_FAIL_DATA_SETUP_COUNTER)) {
    359                 mFailDataSetupCounter = intent.getIntExtra(FAIL_DATA_SETUP_COUNTER, 1);
    360                 mFailDataSetupFailCause = FailCause.fromInt(
    361                         intent.getIntExtra(FAIL_DATA_SETUP_FAIL_CAUSE,
    362                                                     FailCause.ERROR_UNSPECIFIED.getErrorCode()));
    363                 if (DBG) log("set mFailDataSetupCounter=" + mFailDataSetupCounter +
    364                         " mFailDataSetupFailCause=" + mFailDataSetupFailCause);
    365             }
    366         }
    367     };
    368 
    369     private final DataRoamingSettingObserver mDataRoamingSettingObserver;
    370 
    371     private class DataRoamingSettingObserver extends ContentObserver {
    372         public DataRoamingSettingObserver(Handler handler) {
    373             super(handler);
    374         }
    375 
    376         public void register(Context context) {
    377             final ContentResolver resolver = context.getContentResolver();
    378             resolver.registerContentObserver(
    379                     Settings.Secure.getUriFor(Settings.Secure.DATA_ROAMING), false, this);
    380         }
    381 
    382         public void unregister(Context context) {
    383             final ContentResolver resolver = context.getContentResolver();
    384             resolver.unregisterContentObserver(this);
    385         }
    386 
    387         @Override
    388         public void onChange(boolean selfChange) {
    389             // already running on mPhone handler thread
    390             handleDataOnRoamingChange();
    391         }
    392     }
    393 
    394     /**
    395      * Maintian the sum of transmit and receive packets.
    396      *
    397      * The packet counts are initizlied and reset to -1 and
    398      * remain -1 until they can be updated.
    399      */
    400     public class TxRxSum {
    401         public long txPkts;
    402         public long rxPkts;
    403 
    404         public TxRxSum() {
    405             reset();
    406         }
    407 
    408         public TxRxSum(long txPkts, long rxPkts) {
    409             this.txPkts = txPkts;
    410             this.rxPkts = rxPkts;
    411         }
    412 
    413         public TxRxSum(TxRxSum sum) {
    414             txPkts = sum.txPkts;
    415             rxPkts = sum.rxPkts;
    416         }
    417 
    418         public void reset() {
    419             txPkts = -1;
    420             rxPkts = -1;
    421         }
    422 
    423         public String toString() {
    424             return "{txSum=" + txPkts + " rxSum=" + rxPkts + "}";
    425         }
    426 
    427         public void updateTxRxSum() {
    428             boolean txUpdated = false, rxUpdated = false;
    429             long txSum = 0, rxSum = 0;
    430             for (ApnContext apnContext : mApnContexts.values()) {
    431                 if (apnContext.getState() == State.CONNECTED) {
    432                     DataConnectionAc dcac = apnContext.getDataConnectionAc();
    433                     if (dcac == null) continue;
    434 
    435                     LinkProperties linkProp = dcac.getLinkPropertiesSync();
    436                     if (linkProp == null) continue;
    437 
    438                     String iface = linkProp.getInterfaceName();
    439 
    440                     if (iface != null) {
    441                         long stats = TrafficStats.getTxPackets(iface);
    442                         if (stats > 0) {
    443                             txUpdated = true;
    444                             txSum += stats;
    445                         }
    446                         stats = TrafficStats.getRxPackets(iface);
    447                         if (stats > 0) {
    448                             rxUpdated = true;
    449                             rxSum += stats;
    450                         }
    451                     }
    452                 }
    453             }
    454             if (txUpdated) this.txPkts = txSum;
    455             if (rxUpdated) this.rxPkts = rxSum;
    456         }
    457     }
    458 
    459     protected boolean isDataSetupCompleteOk(AsyncResult ar) {
    460         if (ar.exception != null) {
    461             if (DBG) log("isDataSetupCompleteOk return false, ar.result=" + ar.result);
    462             return false;
    463         }
    464         if (mFailDataSetupCounter <= 0) {
    465             if (DBG) log("isDataSetupCompleteOk return true");
    466             return true;
    467         }
    468         ar.result = mFailDataSetupFailCause;
    469         if (DBG) {
    470             log("isDataSetupCompleteOk return false" +
    471                     " mFailDataSetupCounter=" + mFailDataSetupCounter +
    472                     " mFailDataSetupFailCause=" + mFailDataSetupFailCause);
    473         }
    474         mFailDataSetupCounter -= 1;
    475         return false;
    476     }
    477 
    478     protected void onActionIntentReconnectAlarm(Intent intent) {
    479         String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
    480         if (mState == State.FAILED) {
    481             Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
    482             msg.arg1 = 0; // tearDown is false
    483             msg.arg2 = 0;
    484             msg.obj = reason;
    485             sendMessage(msg);
    486         }
    487         sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
    488     }
    489 
    490     protected void onActionIntentDataStallAlarm(Intent intent) {
    491         if (VDBG) log("onActionIntentDataStallAlarm: action=" + intent.getAction());
    492         Message msg = obtainMessage(EVENT_DATA_STALL_ALARM, intent.getAction());
    493         msg.arg1 = intent.getIntExtra(DATA_STALL_ALARM_TAG_EXTRA, 0);
    494         sendMessage(msg);
    495     }
    496 
    497     /**
    498      * Default constructor
    499      */
    500     protected DataConnectionTracker(PhoneBase phone) {
    501         super();
    502         if (DBG) log("DCT.constructor");
    503         mPhone = phone;
    504 
    505         IntentFilter filter = new IntentFilter();
    506         filter.addAction(getActionIntentReconnectAlarm());
    507         filter.addAction(Intent.ACTION_SCREEN_ON);
    508         filter.addAction(Intent.ACTION_SCREEN_OFF);
    509         filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
    510         filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
    511         filter.addAction(INTENT_SET_FAIL_DATA_SETUP_COUNTER);
    512 
    513         mUserDataEnabled = Settings.Secure.getInt(
    514                 mPhone.getContext().getContentResolver(), Settings.Secure.MOBILE_DATA, 1) == 1;
    515 
    516         // TODO: Why is this registering the phone as the receiver of the intent
    517         //       and not its own handler?
    518         mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
    519 
    520         // This preference tells us 1) initial condition for "dataEnabled",
    521         // and 2) whether the RIL will setup the baseband to auto-PS attach.
    522 
    523         dataEnabled[APN_DEFAULT_ID] = SystemProperties.getBoolean(DEFALUT_DATA_ON_BOOT_PROP,
    524                                                                   true);
    525         if (dataEnabled[APN_DEFAULT_ID]) {
    526             enabledCount++;
    527         }
    528 
    529         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
    530         mAutoAttachOnCreation = sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false);
    531 
    532         // watch for changes to Settings.Secure.DATA_ROAMING
    533         mDataRoamingSettingObserver = new DataRoamingSettingObserver(mPhone);
    534         mDataRoamingSettingObserver.register(mPhone.getContext());
    535     }
    536 
    537     public void dispose() {
    538         if (DBG) log("DCT.dispose");
    539         for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
    540             dcac.disconnect();
    541         }
    542         mDataConnectionAsyncChannels.clear();
    543         mIsDisposed = true;
    544         mPhone.getContext().unregisterReceiver(this.mIntentReceiver);
    545         mDataRoamingSettingObserver.unregister(mPhone.getContext());
    546     }
    547 
    548     protected void broadcastMessenger() {
    549         Intent intent = new Intent(ACTION_DATA_CONNECTION_TRACKER_MESSENGER);
    550         intent.putExtra(EXTRA_MESSENGER, new Messenger(this));
    551         mPhone.getContext().sendBroadcast(intent);
    552     }
    553 
    554     public Activity getActivity() {
    555         return mActivity;
    556     }
    557 
    558     public boolean isApnTypeActive(String type) {
    559         // TODO: support simultaneous with List instead
    560         if (Phone.APN_TYPE_DUN.equals(type)) {
    561             ApnSetting dunApn = fetchDunApn();
    562             if (dunApn != null) {
    563                 return ((mActiveApn != null) && (dunApn.toString().equals(mActiveApn.toString())));
    564             }
    565         }
    566         return mActiveApn != null && mActiveApn.canHandleType(type);
    567     }
    568 
    569     protected ApnSetting fetchDunApn() {
    570         if (SystemProperties.getBoolean("net.tethering.noprovisioning", false)) {
    571             log("fetchDunApn: net.tethering.noprovisioning=true ret: null");
    572             return null;
    573         }
    574         Context c = mPhone.getContext();
    575         String apnData = Settings.Secure.getString(c.getContentResolver(),
    576                 Settings.Secure.TETHER_DUN_APN);
    577         ApnSetting dunSetting = ApnSetting.fromString(apnData);
    578         if (dunSetting != null) {
    579             if (VDBG) log("fetchDunApn: secure TETHER_DUN_APN dunSetting=" + dunSetting);
    580             return dunSetting;
    581         }
    582 
    583         apnData = c.getResources().getString(R.string.config_tether_apndata);
    584         dunSetting = ApnSetting.fromString(apnData);
    585         if (VDBG) log("fetchDunApn: config_tether_apndata dunSetting=" + dunSetting);
    586         return dunSetting;
    587     }
    588 
    589     public String[] getActiveApnTypes() {
    590         String[] result;
    591         if (mActiveApn != null) {
    592             result = mActiveApn.types;
    593         } else {
    594             result = new String[1];
    595             result[0] = Phone.APN_TYPE_DEFAULT;
    596         }
    597         return result;
    598     }
    599 
    600     /** TODO: See if we can remove */
    601     public String getActiveApnString(String apnType) {
    602         String result = null;
    603         if (mActiveApn != null) {
    604             result = mActiveApn.apn;
    605         }
    606         return result;
    607     }
    608 
    609     /**
    610      * Modify {@link Settings.Secure#DATA_ROAMING} value.
    611      */
    612     public void setDataOnRoamingEnabled(boolean enabled) {
    613         if (getDataOnRoamingEnabled() != enabled) {
    614             final ContentResolver resolver = mPhone.getContext().getContentResolver();
    615             Settings.Secure.putInt(resolver, Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
    616             // will trigger handleDataOnRoamingChange() through observer
    617         }
    618     }
    619 
    620     /**
    621      * Return current {@link Settings.Secure#DATA_ROAMING} value.
    622      */
    623     public boolean getDataOnRoamingEnabled() {
    624         try {
    625             final ContentResolver resolver = mPhone.getContext().getContentResolver();
    626             return Settings.Secure.getInt(resolver, Settings.Secure.DATA_ROAMING) != 0;
    627         } catch (SettingNotFoundException snfe) {
    628             return false;
    629         }
    630     }
    631 
    632     private void handleDataOnRoamingChange() {
    633         if (mPhone.getServiceState().getRoaming()) {
    634             if (getDataOnRoamingEnabled()) {
    635                 resetAllRetryCounts();
    636             }
    637             sendMessage(obtainMessage(EVENT_ROAMING_ON));
    638         }
    639     }
    640 
    641     // abstract methods
    642     protected abstract String getActionIntentReconnectAlarm();
    643     protected abstract String getActionIntentDataStallAlarm();
    644     protected abstract void startNetStatPoll();
    645     protected abstract void stopNetStatPoll();
    646     protected abstract void restartDataStallAlarm();
    647     protected abstract void restartRadio();
    648     protected abstract void log(String s);
    649     protected abstract void loge(String s);
    650     protected abstract boolean isDataAllowed();
    651     protected abstract boolean isApnTypeAvailable(String type);
    652     public    abstract State getState(String apnType);
    653     protected abstract void setState(State s);
    654     protected abstract void gotoIdleAndNotifyDataConnection(String reason);
    655 
    656     protected abstract boolean onTrySetupData(String reason);
    657     protected abstract void onRoamingOff();
    658     protected abstract void onRoamingOn();
    659     protected abstract void onRadioAvailable();
    660     protected abstract void onRadioOffOrNotAvailable();
    661     protected abstract void onDataSetupComplete(AsyncResult ar);
    662     protected abstract void onDisconnectDone(int connId, AsyncResult ar);
    663     protected abstract void onVoiceCallStarted();
    664     protected abstract void onVoiceCallEnded();
    665     protected abstract void onCleanUpConnection(boolean tearDown, int apnId, String reason);
    666     protected abstract void onCleanUpAllConnections(String cause);
    667     protected abstract boolean isDataPossible(String apnType);
    668 
    669     protected void onDataStallAlarm(int tag) {
    670         loge("onDataStallAlarm: not impleted tag=" + tag);
    671     }
    672 
    673     @Override
    674     public void handleMessage(Message msg) {
    675         switch (msg.what) {
    676             case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
    677                 log("DISCONNECTED_CONNECTED: msg=" + msg);
    678                 DataConnectionAc dcac = (DataConnectionAc) msg.obj;
    679                 mDataConnectionAsyncChannels.remove(dcac.dataConnection.getDataConnectionId());
    680                 dcac.disconnected();
    681                 break;
    682             }
    683             case EVENT_ENABLE_NEW_APN:
    684                 onEnableApn(msg.arg1, msg.arg2);
    685                 break;
    686 
    687             case EVENT_TRY_SETUP_DATA:
    688                 String reason = null;
    689                 if (msg.obj instanceof String) {
    690                     reason = (String) msg.obj;
    691                 }
    692                 onTrySetupData(reason);
    693                 break;
    694 
    695             case EVENT_DATA_STALL_ALARM:
    696                 onDataStallAlarm(msg.arg1);
    697                 break;
    698 
    699             case EVENT_ROAMING_OFF:
    700                 if (getDataOnRoamingEnabled() == false) {
    701                     resetAllRetryCounts();
    702                 }
    703                 onRoamingOff();
    704                 break;
    705 
    706             case EVENT_ROAMING_ON:
    707                 onRoamingOn();
    708                 break;
    709 
    710             case EVENT_RADIO_AVAILABLE:
    711                 onRadioAvailable();
    712                 break;
    713 
    714             case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
    715                 onRadioOffOrNotAvailable();
    716                 break;
    717 
    718             case EVENT_DATA_SETUP_COMPLETE:
    719                 mCidActive = msg.arg1;
    720                 onDataSetupComplete((AsyncResult) msg.obj);
    721                 break;
    722 
    723             case EVENT_DISCONNECT_DONE:
    724                 log("DataConnectoinTracker.handleMessage: EVENT_DISCONNECT_DONE msg=" + msg);
    725                 onDisconnectDone(msg.arg1, (AsyncResult) msg.obj);
    726                 break;
    727 
    728             case EVENT_VOICE_CALL_STARTED:
    729                 onVoiceCallStarted();
    730                 break;
    731 
    732             case EVENT_VOICE_CALL_ENDED:
    733                 onVoiceCallEnded();
    734                 break;
    735 
    736             case EVENT_CLEAN_UP_ALL_CONNECTIONS: {
    737                 onCleanUpAllConnections((String) msg.obj);
    738                 break;
    739             }
    740             case EVENT_CLEAN_UP_CONNECTION: {
    741                 boolean tearDown = (msg.arg1 == 0) ? false : true;
    742                 onCleanUpConnection(tearDown, msg.arg2, (String) msg.obj);
    743                 break;
    744             }
    745             case EVENT_SET_INTERNAL_DATA_ENABLE: {
    746                 boolean enabled = (msg.arg1 == ENABLED) ? true : false;
    747                 onSetInternalDataEnabled(enabled);
    748                 break;
    749             }
    750             case EVENT_RESET_DONE: {
    751                 if (DBG) log("EVENT_RESET_DONE");
    752                 onResetDone((AsyncResult) msg.obj);
    753                 break;
    754             }
    755             case CMD_SET_USER_DATA_ENABLE: {
    756                 final boolean enabled = (msg.arg1 == ENABLED) ? true : false;
    757                 if (DBG) log("CMD_SET_USER_DATA_ENABLE enabled=" + enabled);
    758                 onSetUserDataEnabled(enabled);
    759                 break;
    760             }
    761             case CMD_SET_DEPENDENCY_MET: {
    762                 boolean met = (msg.arg1 == ENABLED) ? true : false;
    763                 if (DBG) log("CMD_SET_DEPENDENCY_MET met=" + met);
    764                 Bundle bundle = msg.getData();
    765                 if (bundle != null) {
    766                     String apnType = (String)bundle.get(APN_TYPE_KEY);
    767                     if (apnType != null) {
    768                         onSetDependencyMet(apnType, met);
    769                     }
    770                 }
    771                 break;
    772             }
    773             case CMD_SET_POLICY_DATA_ENABLE: {
    774                 final boolean enabled = (msg.arg1 == ENABLED) ? true : false;
    775                 onSetPolicyDataEnabled(enabled);
    776                 break;
    777             }
    778             default:
    779                 Log.e("DATA", "Unidentified event msg=" + msg);
    780                 break;
    781         }
    782     }
    783 
    784     /**
    785      * Report on whether data connectivity is enabled
    786      *
    787      * @return {@code false} if data connectivity has been explicitly disabled,
    788      *         {@code true} otherwise.
    789      */
    790     public boolean getAnyDataEnabled() {
    791         final boolean result;
    792         synchronized (mDataEnabledLock) {
    793             result = (mInternalDataEnabled && mUserDataEnabled && sPolicyDataEnabled
    794                     && (enabledCount != 0));
    795         }
    796         if (!result && DBG) log("getAnyDataEnabled " + result);
    797         return result;
    798     }
    799 
    800     protected boolean isEmergency() {
    801         final boolean result;
    802         synchronized (mDataEnabledLock) {
    803             result = mPhone.isInEcm() || mPhone.isInEmergencyCall();
    804         }
    805         log("isEmergency: result=" + result);
    806         return result;
    807     }
    808 
    809     protected int apnTypeToId(String type) {
    810         if (TextUtils.equals(type, Phone.APN_TYPE_DEFAULT)) {
    811             return APN_DEFAULT_ID;
    812         } else if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
    813             return APN_MMS_ID;
    814         } else if (TextUtils.equals(type, Phone.APN_TYPE_SUPL)) {
    815             return APN_SUPL_ID;
    816         } else if (TextUtils.equals(type, Phone.APN_TYPE_DUN)) {
    817             return APN_DUN_ID;
    818         } else if (TextUtils.equals(type, Phone.APN_TYPE_HIPRI)) {
    819             return APN_HIPRI_ID;
    820         } else if (TextUtils.equals(type, Phone.APN_TYPE_IMS)) {
    821             return APN_IMS_ID;
    822         } else if (TextUtils.equals(type, Phone.APN_TYPE_FOTA)) {
    823             return APN_FOTA_ID;
    824         } else if (TextUtils.equals(type, Phone.APN_TYPE_CBS)) {
    825             return APN_CBS_ID;
    826         } else {
    827             return APN_INVALID_ID;
    828         }
    829     }
    830 
    831     protected String apnIdToType(int id) {
    832         switch (id) {
    833         case APN_DEFAULT_ID:
    834             return Phone.APN_TYPE_DEFAULT;
    835         case APN_MMS_ID:
    836             return Phone.APN_TYPE_MMS;
    837         case APN_SUPL_ID:
    838             return Phone.APN_TYPE_SUPL;
    839         case APN_DUN_ID:
    840             return Phone.APN_TYPE_DUN;
    841         case APN_HIPRI_ID:
    842             return Phone.APN_TYPE_HIPRI;
    843         case APN_IMS_ID:
    844             return Phone.APN_TYPE_IMS;
    845         case APN_FOTA_ID:
    846             return Phone.APN_TYPE_FOTA;
    847         case APN_CBS_ID:
    848             return Phone.APN_TYPE_CBS;
    849         default:
    850             log("Unknown id (" + id + ") in apnIdToType");
    851             return Phone.APN_TYPE_DEFAULT;
    852         }
    853     }
    854 
    855     protected LinkProperties getLinkProperties(String apnType) {
    856         int id = apnTypeToId(apnType);
    857 
    858         if (isApnIdEnabled(id)) {
    859             // TODO - remove this cdma-only hack and support multiple DCs.
    860             DataConnectionAc dcac = mDataConnectionAsyncChannels.get(0);
    861             return dcac.getLinkPropertiesSync();
    862         } else {
    863             return new LinkProperties();
    864         }
    865     }
    866 
    867     protected LinkCapabilities getLinkCapabilities(String apnType) {
    868         int id = apnTypeToId(apnType);
    869         if (isApnIdEnabled(id)) {
    870             // TODO - remove this cdma-only hack and support multiple DCs.
    871             DataConnectionAc dcac = mDataConnectionAsyncChannels.get(0);
    872             return dcac.getLinkCapabilitiesSync();
    873         } else {
    874             return new LinkCapabilities();
    875         }
    876     }
    877 
    878     // tell all active apns of the current condition
    879     protected void notifyDataConnection(String reason) {
    880         for (int id = 0; id < APN_NUM_TYPES; id++) {
    881             if (dataEnabled[id]) {
    882                 mPhone.notifyDataConnection(reason, apnIdToType(id));
    883             }
    884         }
    885         notifyOffApnsOfAvailability(reason);
    886     }
    887 
    888     // a new APN has gone active and needs to send events to catch up with the
    889     // current condition
    890     private void notifyApnIdUpToCurrent(String reason, int apnId) {
    891         switch (mState) {
    892             case IDLE:
    893             case INITING:
    894                 break;
    895             case CONNECTING:
    896             case SCANNING:
    897                 mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTING);
    898                 break;
    899             case CONNECTED:
    900             case DISCONNECTING:
    901                 mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTING);
    902                 mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.CONNECTED);
    903                 break;
    904         }
    905     }
    906 
    907     // since we normally don't send info to a disconnected APN, we need to do this specially
    908     private void notifyApnIdDisconnected(String reason, int apnId) {
    909         mPhone.notifyDataConnection(reason, apnIdToType(apnId), Phone.DataState.DISCONNECTED);
    910     }
    911 
    912     // disabled apn's still need avail/unavail notificiations - send them out
    913     protected void notifyOffApnsOfAvailability(String reason) {
    914         if (DBG) log("notifyOffApnsOfAvailability - reason= " + reason);
    915         for (int id = 0; id < APN_NUM_TYPES; id++) {
    916             if (!isApnIdEnabled(id)) {
    917                 notifyApnIdDisconnected(reason, id);
    918             }
    919         }
    920     }
    921 
    922     public boolean isApnTypeEnabled(String apnType) {
    923         if (apnType == null) {
    924             return false;
    925         } else {
    926             return isApnIdEnabled(apnTypeToId(apnType));
    927         }
    928     }
    929 
    930     protected synchronized boolean isApnIdEnabled(int id) {
    931         if (id != APN_INVALID_ID) {
    932             return dataEnabled[id];
    933         }
    934         return false;
    935     }
    936 
    937     /**
    938      * Ensure that we are connected to an APN of the specified type.
    939      *
    940      * @param type the APN type (currently the only valid values are
    941      *            {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL})
    942      * @return Success is indicated by {@code Phone.APN_ALREADY_ACTIVE} or
    943      *         {@code Phone.APN_REQUEST_STARTED}. In the latter case, a
    944      *         broadcast will be sent by the ConnectivityManager when a
    945      *         connection to the APN has been established.
    946      */
    947     public synchronized int enableApnType(String type) {
    948         int id = apnTypeToId(type);
    949         if (id == APN_INVALID_ID) {
    950             return Phone.APN_REQUEST_FAILED;
    951         }
    952 
    953         if (DBG) {
    954             log("enableApnType(" + type + "), isApnTypeActive = " + isApnTypeActive(type)
    955                     + ", isApnIdEnabled =" + isApnIdEnabled(id) + " and state = " + mState);
    956         }
    957 
    958         if (!isApnTypeAvailable(type)) {
    959             if (DBG) log("type not available");
    960             return Phone.APN_TYPE_NOT_AVAILABLE;
    961         }
    962 
    963         if (isApnIdEnabled(id)) {
    964             return Phone.APN_ALREADY_ACTIVE;
    965         } else {
    966             setEnabled(id, true);
    967         }
    968         return Phone.APN_REQUEST_STARTED;
    969     }
    970 
    971     /**
    972      * The APN of the specified type is no longer needed. Ensure that if use of
    973      * the default APN has not been explicitly disabled, we are connected to the
    974      * default APN.
    975      *
    976      * @param type the APN type. The only valid values are currently
    977      *            {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}.
    978      * @return Success is indicated by {@code Phone.APN_ALREADY_ACTIVE} or
    979      *         {@code Phone.APN_REQUEST_STARTED}. In the latter case, a
    980      *         broadcast will be sent by the ConnectivityManager when a
    981      *         connection to the APN has been disconnected. A {@code
    982      *         Phone.APN_REQUEST_FAILED} is returned if the type parameter is
    983      *         invalid or if the apn wasn't enabled.
    984      */
    985     public synchronized int disableApnType(String type) {
    986         if (DBG) log("disableApnType(" + type + ")");
    987         int id = apnTypeToId(type);
    988         if (id == APN_INVALID_ID) {
    989             return Phone.APN_REQUEST_FAILED;
    990         }
    991         if (isApnIdEnabled(id)) {
    992             setEnabled(id, false);
    993             if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
    994                 if (dataEnabled[APN_DEFAULT_ID]) {
    995                     return Phone.APN_ALREADY_ACTIVE;
    996                 } else {
    997                     return Phone.APN_REQUEST_STARTED;
    998                 }
    999             } else {
   1000                 return Phone.APN_REQUEST_STARTED;
   1001             }
   1002         } else {
   1003             return Phone.APN_REQUEST_FAILED;
   1004         }
   1005     }
   1006 
   1007     protected void setEnabled(int id, boolean enable) {
   1008         if (DBG) {
   1009             log("setEnabled(" + id + ", " + enable + ") with old state = " + dataEnabled[id]
   1010                     + " and enabledCount = " + enabledCount);
   1011         }
   1012         Message msg = obtainMessage(EVENT_ENABLE_NEW_APN);
   1013         msg.arg1 = id;
   1014         msg.arg2 = (enable ? ENABLED : DISABLED);
   1015         sendMessage(msg);
   1016     }
   1017 
   1018     protected void onEnableApn(int apnId, int enabled) {
   1019         if (DBG) {
   1020             log("EVENT_APN_ENABLE_REQUEST apnId=" + apnId + ", apnType=" + apnIdToType(apnId) +
   1021                     ", enabled=" + enabled + ", dataEnabled = " + dataEnabled[apnId] +
   1022                     ", enabledCount = " + enabledCount + ", isApnTypeActive = " +
   1023                     isApnTypeActive(apnIdToType(apnId)));
   1024         }
   1025         if (enabled == ENABLED) {
   1026             synchronized (this) {
   1027                 if (!dataEnabled[apnId]) {
   1028                     dataEnabled[apnId] = true;
   1029                     enabledCount++;
   1030                 }
   1031             }
   1032             String type = apnIdToType(apnId);
   1033             if (!isApnTypeActive(type)) {
   1034                 mRequestedApnType = type;
   1035                 onEnableNewApn();
   1036             } else {
   1037                 notifyApnIdUpToCurrent(Phone.REASON_APN_SWITCHED, apnId);
   1038             }
   1039         } else {
   1040             // disable
   1041             boolean didDisable = false;
   1042             synchronized (this) {
   1043                 if (dataEnabled[apnId]) {
   1044                     dataEnabled[apnId] = false;
   1045                     enabledCount--;
   1046                     didDisable = true;
   1047                 }
   1048             }
   1049             if (didDisable) {
   1050                 if ((enabledCount == 0) || (apnId == APN_DUN_ID)) {
   1051                     mRequestedApnType = Phone.APN_TYPE_DEFAULT;
   1052                     onCleanUpConnection(true, apnId, Phone.REASON_DATA_DISABLED);
   1053                 }
   1054 
   1055                 // send the disconnect msg manually, since the normal route wont send
   1056                 // it (it's not enabled)
   1057                 notifyApnIdDisconnected(Phone.REASON_DATA_DISABLED, apnId);
   1058                 if (dataEnabled[APN_DEFAULT_ID] == true
   1059                         && !isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
   1060                     // TODO - this is an ugly way to restore the default conn - should be done
   1061                     // by a real contention manager and policy that disconnects the lower pri
   1062                     // stuff as enable requests come in and pops them back on as we disable back
   1063                     // down to the lower pri stuff
   1064                     mRequestedApnType = Phone.APN_TYPE_DEFAULT;
   1065                     onEnableNewApn();
   1066                 }
   1067             }
   1068         }
   1069     }
   1070 
   1071     /**
   1072      * Called when we switch APNs.
   1073      *
   1074      * mRequestedApnType is set prior to call
   1075      * To be overridden.
   1076      */
   1077     protected void onEnableNewApn() {
   1078     }
   1079 
   1080     /**
   1081      * Called when EVENT_RESET_DONE is received so goto
   1082      * IDLE state and send notifications to those interested.
   1083      *
   1084      * TODO - currently unused.  Needs to be hooked into DataConnection cleanup
   1085      * TODO - needs to pass some notion of which connection is reset..
   1086      */
   1087     protected void onResetDone(AsyncResult ar) {
   1088         if (DBG) log("EVENT_RESET_DONE");
   1089         String reason = null;
   1090         if (ar.userObj instanceof String) {
   1091             reason = (String) ar.userObj;
   1092         }
   1093         gotoIdleAndNotifyDataConnection(reason);
   1094     }
   1095 
   1096     /**
   1097      * Prevent mobile data connections from being established, or once again
   1098      * allow mobile data connections. If the state toggles, then either tear
   1099      * down or set up data, as appropriate to match the new state.
   1100      *
   1101      * @param enable indicates whether to enable ({@code true}) or disable (
   1102      *            {@code false}) data
   1103      * @return {@code true} if the operation succeeded
   1104      */
   1105     public boolean setInternalDataEnabled(boolean enable) {
   1106         if (DBG)
   1107             log("setInternalDataEnabled(" + enable + ")");
   1108 
   1109         Message msg = obtainMessage(EVENT_SET_INTERNAL_DATA_ENABLE);
   1110         msg.arg1 = (enable ? ENABLED : DISABLED);
   1111         sendMessage(msg);
   1112         return true;
   1113     }
   1114 
   1115     protected void onSetInternalDataEnabled(boolean enabled) {
   1116         synchronized (mDataEnabledLock) {
   1117             mInternalDataEnabled = enabled;
   1118             if (enabled) {
   1119                 log("onSetInternalDataEnabled: changed to enabled, try to setup data call");
   1120                 resetAllRetryCounts();
   1121                 onTrySetupData(Phone.REASON_DATA_ENABLED);
   1122             } else {
   1123                 log("onSetInternalDataEnabled: changed to disabled, cleanUpAllConnections");
   1124                 cleanUpAllConnections(null);
   1125             }
   1126         }
   1127     }
   1128 
   1129     public void cleanUpAllConnections(String cause) {
   1130         Message msg = obtainMessage(EVENT_CLEAN_UP_ALL_CONNECTIONS);
   1131         msg.obj = cause;
   1132         sendMessage(msg);
   1133     }
   1134 
   1135     public abstract boolean isDisconnected();
   1136 
   1137     protected void onSetUserDataEnabled(boolean enabled) {
   1138         synchronized (mDataEnabledLock) {
   1139             final boolean prevEnabled = getAnyDataEnabled();
   1140             if (mUserDataEnabled != enabled) {
   1141                 mUserDataEnabled = enabled;
   1142                 Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
   1143                         Settings.Secure.MOBILE_DATA, enabled ? 1 : 0);
   1144                 if (getDataOnRoamingEnabled() == false &&
   1145                         mPhone.getServiceState().getRoaming() == true) {
   1146                     if (enabled) {
   1147                         notifyOffApnsOfAvailability(Phone.REASON_ROAMING_ON);
   1148                     } else {
   1149                         notifyOffApnsOfAvailability(Phone.REASON_DATA_DISABLED);
   1150                     }
   1151                 }
   1152                 if (prevEnabled != getAnyDataEnabled()) {
   1153                     if (!prevEnabled) {
   1154                         resetAllRetryCounts();
   1155                         onTrySetupData(Phone.REASON_DATA_ENABLED);
   1156                     } else {
   1157                         onCleanUpAllConnections(Phone.REASON_DATA_DISABLED);
   1158                     }
   1159                 }
   1160             }
   1161         }
   1162     }
   1163 
   1164     protected void onSetDependencyMet(String apnType, boolean met) {
   1165     }
   1166 
   1167     protected void onSetPolicyDataEnabled(boolean enabled) {
   1168         synchronized (mDataEnabledLock) {
   1169             final boolean prevEnabled = getAnyDataEnabled();
   1170             if (sPolicyDataEnabled != enabled) {
   1171                 sPolicyDataEnabled = enabled;
   1172                 if (prevEnabled != getAnyDataEnabled()) {
   1173                     if (!prevEnabled) {
   1174                         resetAllRetryCounts();
   1175                         onTrySetupData(Phone.REASON_DATA_ENABLED);
   1176                     } else {
   1177                         onCleanUpAllConnections(Phone.REASON_DATA_DISABLED);
   1178                     }
   1179                 }
   1180             }
   1181         }
   1182     }
   1183 
   1184     protected String getReryConfig(boolean forDefault) {
   1185         int nt = mPhone.getServiceState().getNetworkType();
   1186 
   1187         if ((nt == TelephonyManager.NETWORK_TYPE_CDMA) ||
   1188             (nt == TelephonyManager.NETWORK_TYPE_1xRTT) ||
   1189             (nt == TelephonyManager.NETWORK_TYPE_EVDO_0) ||
   1190             (nt == TelephonyManager.NETWORK_TYPE_EVDO_A) ||
   1191             (nt == TelephonyManager.NETWORK_TYPE_EVDO_B) ||
   1192             (nt == TelephonyManager.NETWORK_TYPE_EHRPD)) {
   1193             // CDMA variant
   1194             return SystemProperties.get("ro.cdma.data_retry_config");
   1195         } else {
   1196             // Use GSM varient for all others.
   1197             if (forDefault) {
   1198                 return SystemProperties.get("ro.gsm.data_retry_config");
   1199             } else {
   1200                 return SystemProperties.get("ro.gsm.2nd_data_retry_config");
   1201             }
   1202         }
   1203     }
   1204 
   1205     protected void resetAllRetryCounts() {
   1206         for (DataConnection dc : mDataConnections.values()) {
   1207             dc.resetRetryCount();
   1208         }
   1209     }
   1210 
   1211     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   1212         pw.println("DataConnectionTracker:");
   1213         pw.println(" mInternalDataEnabled=" + mInternalDataEnabled);
   1214         pw.println(" mUserDataEnabled=" + mUserDataEnabled);
   1215         pw.println(" sPolicyDataEnabed=" + sPolicyDataEnabled);
   1216         pw.println(" dataEnabled:");
   1217         for(int i=0; i < dataEnabled.length; i++) {
   1218             pw.printf("  dataEnabled[%d]=%b\n", i, dataEnabled[i]);
   1219         }
   1220         pw.flush();
   1221         pw.println(" enabledCount=" + enabledCount);
   1222         pw.println(" mRequestedApnType=" + mRequestedApnType);
   1223         pw.println(" mPhone=" + mPhone.getPhoneName());
   1224         pw.println(" mActivity=" + mActivity);
   1225         pw.println(" mState=" + mState);
   1226         pw.println(" mTxPkts=" + mTxPkts);
   1227         pw.println(" mRxPkts=" + mRxPkts);
   1228         pw.println(" mNetStatPollPeriod=" + mNetStatPollPeriod);
   1229         pw.println(" mNetStatPollEnabled=" + mNetStatPollEnabled);
   1230         pw.println(" mDataStallTxRxSum=" + mDataStallTxRxSum);
   1231         pw.println(" mDataStallAlarmTag=" + mDataStallAlarmTag);
   1232         pw.println(" mSentSinceLastRecv=" + mSentSinceLastRecv);
   1233         pw.println(" mNoRecvPollCount=" + mNoRecvPollCount);
   1234         pw.println(" mIsWifiConnected=" + mIsWifiConnected);
   1235         pw.println(" mReconnectIntent=" + mReconnectIntent);
   1236         pw.println(" mCidActive=" + mCidActive);
   1237         pw.println(" mAutoAttachOnCreation=" + mAutoAttachOnCreation);
   1238         pw.println(" mIsScreenOn=" + mIsScreenOn);
   1239         pw.println(" mUniqueIdGenerator=" + mUniqueIdGenerator);
   1240         pw.flush();
   1241         pw.println(" ***************************************");
   1242         Set<Entry<Integer, DataConnection> > mDcSet = mDataConnections.entrySet();
   1243         pw.println(" mDataConnections: count=" + mDcSet.size());
   1244         for (Entry<Integer, DataConnection> entry : mDcSet) {
   1245             pw.printf(" *** mDataConnection[%d] \n", entry.getKey());
   1246             entry.getValue().dump(fd, pw, args);
   1247         }
   1248         pw.println(" ***************************************");
   1249         pw.flush();
   1250         Set<Entry<String, Integer>> mApnToDcIdSet = mApnToDataConnectionId.entrySet();
   1251         pw.println(" mApnToDataConnectonId size=" + mApnToDcIdSet.size());
   1252         for (Entry<String, Integer> entry : mApnToDcIdSet) {
   1253             pw.printf(" mApnToDataConnectonId[%s]=%d\n", entry.getKey(), entry.getValue());
   1254         }
   1255         pw.println(" ***************************************");
   1256         pw.flush();
   1257         if (mApnContexts != null) {
   1258             Set<Entry<String, ApnContext>> mApnContextsSet = mApnContexts.entrySet();
   1259             pw.println(" mApnContexts size=" + mApnContextsSet.size());
   1260             for (Entry<String, ApnContext> entry : mApnContextsSet) {
   1261                 entry.getValue().dump(fd, pw, args);
   1262             }
   1263             pw.println(" ***************************************");
   1264         } else {
   1265             pw.println(" mApnContexts=null");
   1266         }
   1267         pw.flush();
   1268         pw.println(" mActiveApn=" + mActiveApn);
   1269         if (mAllApns != null) {
   1270             pw.println(" mAllApns size=" + mAllApns.size());
   1271             for (int i=0; i < mAllApns.size(); i++) {
   1272                 pw.printf(" mAllApns[%d]: %s\n", i, mAllApns.get(i));
   1273             }
   1274             pw.flush();
   1275         } else {
   1276             pw.println(" mAllApns=null");
   1277         }
   1278         pw.println(" mPreferredApn=" + mPreferredApn);
   1279         pw.println(" mIsPsRestricted=" + mIsPsRestricted);
   1280         pw.println(" mIsDisposed=" + mIsDisposed);
   1281         pw.println(" mIntentReceiver=" + mIntentReceiver);
   1282         pw.println(" mDataRoamingSettingObserver=" + mDataRoamingSettingObserver);
   1283         pw.flush();
   1284     }
   1285 }
   1286