Home | History | Annotate | Download | only in dataconnection
      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.dataconnection;
     18 
     19 import com.android.internal.telephony.CallTracker;
     20 import com.android.internal.telephony.CommandException;
     21 import com.android.internal.telephony.DctConstants;
     22 import com.android.internal.telephony.Phone;
     23 import com.android.internal.telephony.PhoneBase;
     24 import com.android.internal.telephony.PhoneConstants;
     25 import com.android.internal.telephony.RILConstants;
     26 import com.android.internal.telephony.RetryManager;
     27 import com.android.internal.telephony.ServiceStateTracker;
     28 import com.android.internal.util.AsyncChannel;
     29 import com.android.internal.util.FastPrintWriter;
     30 import com.android.internal.util.Protocol;
     31 import com.android.internal.util.State;
     32 import com.android.internal.util.StateMachine;
     33 
     34 import android.app.PendingIntent;
     35 import android.content.Context;
     36 import android.net.ConnectivityManager;
     37 import android.net.LinkProperties;
     38 import android.net.NetworkAgent;
     39 import android.net.NetworkCapabilities;
     40 import android.net.NetworkInfo;
     41 import android.net.NetworkMisc;
     42 import android.net.ProxyInfo;
     43 import android.os.AsyncResult;
     44 import android.os.Build;
     45 import android.os.Looper;
     46 import android.os.Message;
     47 import android.os.Messenger;
     48 import android.os.SystemClock;
     49 import android.os.SystemProperties;
     50 import android.telephony.Rlog;
     51 import android.telephony.ServiceState;
     52 import android.telephony.TelephonyManager;
     53 import android.text.TextUtils;
     54 import android.util.Pair;
     55 import android.util.Patterns;
     56 import android.util.TimeUtils;
     57 
     58 import java.io.FileDescriptor;
     59 import java.io.OutputStream;
     60 import java.io.PrintWriter;
     61 import java.io.StringWriter;
     62 import java.util.ArrayList;
     63 import java.util.List;
     64 import java.util.Locale;
     65 import java.util.concurrent.atomic.AtomicInteger;
     66 import java.net.InetAddress;
     67 import java.util.Collection;
     68 
     69 /**
     70  * {@hide}
     71  *
     72  * DataConnection StateMachine.
     73  *
     74  * This a class for representing a single data connection, with instances of this
     75  * class representing a connection via the cellular network. There may be multiple
     76  * data connections and all of them are managed by the <code>DataConnectionTracker</code>.
     77  *
     78  * A recent change is to move retry handling into this class, with that change the
     79  * old retry manager is now used internally rather than exposed to the DCT. Also,
     80  * bringUp now has an initialRetry which is used limit the number of retries
     81  * during the initial bring up of the connection. After the connection becomes active
     82  * the current max retry is restored to the configured value.
     83  *
     84  * NOTE: All DataConnection objects must be running on the same looper, which is the default
     85  * as the coordinator has members which are used without synchronization.
     86  */
     87 public final class DataConnection extends StateMachine {
     88     private static final boolean DBG = true;
     89     private static final boolean VDBG = true;
     90 
     91     /** Retry configuration: A doubling of retry times from 5secs to 30minutes */
     92     private static final String DEFAULT_DATA_RETRY_CONFIG = "default_randomization=2000,"
     93         + "5000,10000,20000,40000,80000:5000,160000:5000,"
     94         + "320000:5000,640000:5000,1280000:5000,1800000:5000";
     95 
     96     /** Retry configuration for secondary networks: 4 tries in 20 sec */
     97     private static final String SECONDARY_DATA_RETRY_CONFIG =
     98             "max_retries=3, 5000, 5000, 5000";
     99 
    100     private static final String NETWORK_TYPE = "MOBILE";
    101 
    102     // The data connection controller
    103     private DcController mDcController;
    104 
    105     // The Tester for failing all bringup's
    106     private DcTesterFailBringUpAll mDcTesterFailBringUpAll;
    107 
    108     private static AtomicInteger mInstanceNumber = new AtomicInteger(0);
    109     private AsyncChannel mAc;
    110 
    111     // Utilities for the DataConnection
    112     private DcRetryAlarmController mDcRetryAlarmController;
    113 
    114     // The DCT that's talking to us, we only support one!
    115     private DcTrackerBase mDct = null;
    116 
    117     protected String[] mPcscfAddr;
    118 
    119     /**
    120      * Used internally for saving connecting parameters.
    121      */
    122     static class ConnectionParams {
    123         int mTag;
    124         ApnContext mApnContext;
    125         int mInitialMaxRetry;
    126         int mProfileId;
    127         int mRilRat;
    128         boolean mRetryWhenSSChange;
    129         Message mOnCompletedMsg;
    130 
    131         ConnectionParams(ApnContext apnContext, int initialMaxRetry, int profileId,
    132                 int rilRadioTechnology, boolean retryWhenSSChange, Message onCompletedMsg) {
    133             mApnContext = apnContext;
    134             mInitialMaxRetry = initialMaxRetry;
    135             mProfileId = profileId;
    136             mRilRat = rilRadioTechnology;
    137             mRetryWhenSSChange = retryWhenSSChange;
    138             mOnCompletedMsg = onCompletedMsg;
    139         }
    140 
    141         @Override
    142         public String toString() {
    143             return "{mTag=" + mTag + " mApnContext=" + mApnContext
    144                     + " mInitialMaxRetry=" + mInitialMaxRetry + " mProfileId=" + mProfileId
    145                     + " mRat=" + mRilRat
    146                     + " mOnCompletedMsg=" + msgToString(mOnCompletedMsg) + "}";
    147         }
    148     }
    149 
    150     /**
    151      * Used internally for saving disconnecting parameters.
    152      */
    153     static class DisconnectParams {
    154         int mTag;
    155         ApnContext mApnContext;
    156         String mReason;
    157         Message mOnCompletedMsg;
    158 
    159         DisconnectParams(ApnContext apnContext, String reason, Message onCompletedMsg) {
    160             mApnContext = apnContext;
    161             mReason = reason;
    162             mOnCompletedMsg = onCompletedMsg;
    163         }
    164 
    165         @Override
    166         public String toString() {
    167             return "{mTag=" + mTag + " mApnContext=" + mApnContext
    168                     + " mReason=" + mReason
    169                     + " mOnCompletedMsg=" + msgToString(mOnCompletedMsg) + "}";
    170         }
    171     }
    172 
    173     private ApnSetting mApnSetting;
    174     private ConnectionParams mConnectionParams;
    175     private DisconnectParams mDisconnectParams;
    176     private DcFailCause mDcFailCause;
    177 
    178     private PhoneBase mPhone;
    179     private LinkProperties mLinkProperties = new LinkProperties();
    180     private long mCreateTime;
    181     private long mLastFailTime;
    182     private DcFailCause mLastFailCause;
    183     private static final String NULL_IP = "0.0.0.0";
    184     private Object mUserData;
    185     private int mRilRat = Integer.MAX_VALUE;
    186     private int mDataRegState = Integer.MAX_VALUE;
    187     private NetworkInfo mNetworkInfo;
    188     private NetworkAgent mNetworkAgent;
    189 
    190     //***** Package visible variables
    191     int mTag;
    192     int mCid;
    193     List<ApnContext> mApnContexts = null;
    194     PendingIntent mReconnectIntent = null;
    195     RetryManager mRetryManager = new RetryManager();
    196 
    197 
    198     // ***** Event codes for driving the state machine, package visible for Dcc
    199     static final int BASE = Protocol.BASE_DATA_CONNECTION;
    200     static final int EVENT_CONNECT = BASE + 0;
    201     static final int EVENT_SETUP_DATA_CONNECTION_DONE = BASE + 1;
    202     static final int EVENT_GET_LAST_FAIL_DONE = BASE + 2;
    203     static final int EVENT_DEACTIVATE_DONE = BASE + 3;
    204     static final int EVENT_DISCONNECT = BASE + 4;
    205     static final int EVENT_RIL_CONNECTED = BASE + 5;
    206     static final int EVENT_DISCONNECT_ALL = BASE + 6;
    207     static final int EVENT_DATA_STATE_CHANGED = BASE + 7;
    208     static final int EVENT_TEAR_DOWN_NOW = BASE + 8;
    209     static final int EVENT_LOST_CONNECTION = BASE + 9;
    210     static final int EVENT_RETRY_CONNECTION = BASE + 10;
    211     static final int EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED = BASE + 11;
    212     static final int EVENT_DATA_CONNECTION_ROAM_ON = BASE + 12;
    213     static final int EVENT_DATA_CONNECTION_ROAM_OFF = BASE + 13;
    214     static final int EVENT_BW_REFRESH_RESPONSE = BASE + 14;
    215     static final int EVENT_DATA_CONNECTION_VOICE_CALL_STARTED = BASE + 15;
    216     static final int EVENT_DATA_CONNECTION_VOICE_CALL_ENDED = BASE + 16;
    217 
    218     private static final int CMD_TO_STRING_COUNT =
    219             EVENT_DATA_CONNECTION_VOICE_CALL_ENDED - BASE + 1;
    220 
    221     private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT];
    222     static {
    223         sCmdToString[EVENT_CONNECT - BASE] = "EVENT_CONNECT";
    224         sCmdToString[EVENT_SETUP_DATA_CONNECTION_DONE - BASE] =
    225                 "EVENT_SETUP_DATA_CONNECTION_DONE";
    226         sCmdToString[EVENT_GET_LAST_FAIL_DONE - BASE] = "EVENT_GET_LAST_FAIL_DONE";
    227         sCmdToString[EVENT_DEACTIVATE_DONE - BASE] = "EVENT_DEACTIVATE_DONE";
    228         sCmdToString[EVENT_DISCONNECT - BASE] = "EVENT_DISCONNECT";
    229         sCmdToString[EVENT_RIL_CONNECTED - BASE] = "EVENT_RIL_CONNECTED";
    230         sCmdToString[EVENT_DISCONNECT_ALL - BASE] = "EVENT_DISCONNECT_ALL";
    231         sCmdToString[EVENT_DATA_STATE_CHANGED - BASE] = "EVENT_DATA_STATE_CHANGED";
    232         sCmdToString[EVENT_TEAR_DOWN_NOW - BASE] = "EVENT_TEAR_DOWN_NOW";
    233         sCmdToString[EVENT_LOST_CONNECTION - BASE] = "EVENT_LOST_CONNECTION";
    234         sCmdToString[EVENT_RETRY_CONNECTION - BASE] = "EVENT_RETRY_CONNECTION";
    235         sCmdToString[EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED - BASE] =
    236                 "EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED";
    237         sCmdToString[EVENT_DATA_CONNECTION_ROAM_ON - BASE] = "EVENT_DATA_CONNECTION_ROAM_ON";
    238         sCmdToString[EVENT_DATA_CONNECTION_ROAM_OFF - BASE] = "EVENT_DATA_CONNECTION_ROAM_OFF";
    239         sCmdToString[EVENT_BW_REFRESH_RESPONSE - BASE] = "EVENT_BW_REFRESH_RESPONSE";
    240         sCmdToString[EVENT_DATA_CONNECTION_VOICE_CALL_STARTED - BASE] =
    241                 "EVENT_DATA_CONNECTION_VOICE_CALL_STARTED";
    242         sCmdToString[EVENT_DATA_CONNECTION_VOICE_CALL_ENDED - BASE] =
    243                 "EVENT_DATA_CONNECTION_VOICE_CALL_ENDED";
    244     }
    245     // Convert cmd to string or null if unknown
    246     static String cmdToString(int cmd) {
    247         String value;
    248         cmd -= BASE;
    249         if ((cmd >= 0) && (cmd < sCmdToString.length)) {
    250             value = sCmdToString[cmd];
    251         } else {
    252             value = DcAsyncChannel.cmdToString(cmd + BASE);
    253         }
    254         if (value == null) {
    255             value = "0x" + Integer.toHexString(cmd + BASE);
    256         }
    257         return value;
    258     }
    259 
    260     /**
    261      * Create the connection object
    262      *
    263      * @param phone the Phone
    264      * @param id the connection id
    265      * @return DataConnection that was created.
    266      */
    267     static DataConnection makeDataConnection(PhoneBase phone, int id,
    268             DcTrackerBase dct, DcTesterFailBringUpAll failBringUpAll,
    269             DcController dcc) {
    270         DataConnection dc = new DataConnection(phone,
    271                 "DC-" + mInstanceNumber.incrementAndGet(), id, dct, failBringUpAll, dcc);
    272         dc.start();
    273         if (DBG) dc.log("Made " + dc.getName());
    274         return dc;
    275     }
    276 
    277     void dispose() {
    278         log("dispose: call quiteNow()");
    279         quitNow();
    280     }
    281 
    282     /* Getter functions */
    283 
    284     NetworkCapabilities getCopyNetworkCapabilities() {
    285         return makeNetworkCapabilities();
    286     }
    287 
    288     LinkProperties getCopyLinkProperties() {
    289         return new LinkProperties(mLinkProperties);
    290     }
    291 
    292     boolean getIsInactive() {
    293         return getCurrentState() == mInactiveState;
    294     }
    295 
    296     int getCid() {
    297         return mCid;
    298     }
    299 
    300     ApnSetting getApnSetting() {
    301         return mApnSetting;
    302     }
    303 
    304     void setLinkPropertiesHttpProxy(ProxyInfo proxy) {
    305         mLinkProperties.setHttpProxy(proxy);
    306     }
    307 
    308     static class UpdateLinkPropertyResult {
    309         public DataCallResponse.SetupResult setupResult = DataCallResponse.SetupResult.SUCCESS;
    310         public LinkProperties oldLp;
    311         public LinkProperties newLp;
    312         public UpdateLinkPropertyResult(LinkProperties curLp) {
    313             oldLp = curLp;
    314             newLp = curLp;
    315         }
    316     }
    317 
    318     public boolean isIpv4Connected() {
    319         boolean ret = false;
    320         Collection <InetAddress> addresses = mLinkProperties.getAddresses();
    321 
    322         for (InetAddress addr: addresses) {
    323             if (addr instanceof java.net.Inet4Address) {
    324                 java.net.Inet4Address i4addr = (java.net.Inet4Address) addr;
    325                 if (!i4addr.isAnyLocalAddress() && !i4addr.isLinkLocalAddress() &&
    326                         !i4addr.isLoopbackAddress() && !i4addr.isMulticastAddress()) {
    327                     ret = true;
    328                     break;
    329                 }
    330             }
    331         }
    332         return ret;
    333     }
    334 
    335     public boolean isIpv6Connected() {
    336         boolean ret = false;
    337         Collection <InetAddress> addresses = mLinkProperties.getAddresses();
    338 
    339         for (InetAddress addr: addresses) {
    340             if (addr instanceof java.net.Inet6Address) {
    341                 java.net.Inet6Address i6addr = (java.net.Inet6Address) addr;
    342                 if (!i6addr.isAnyLocalAddress() && !i6addr.isLinkLocalAddress() &&
    343                         !i6addr.isLoopbackAddress() && !i6addr.isMulticastAddress()) {
    344                     ret = true;
    345                     break;
    346                 }
    347             }
    348         }
    349         return ret;
    350     }
    351 
    352     UpdateLinkPropertyResult updateLinkProperty(DataCallResponse newState) {
    353         UpdateLinkPropertyResult result = new UpdateLinkPropertyResult(mLinkProperties);
    354 
    355         if (newState == null) return result;
    356 
    357         DataCallResponse.SetupResult setupResult;
    358         result.newLp = new LinkProperties();
    359 
    360         // set link properties based on data call response
    361         result.setupResult = setLinkProperties(newState, result.newLp);
    362         if (result.setupResult != DataCallResponse.SetupResult.SUCCESS) {
    363             if (DBG) log("updateLinkProperty failed : " + result.setupResult);
    364             return result;
    365         }
    366         // copy HTTP proxy as it is not part DataCallResponse.
    367         result.newLp.setHttpProxy(mLinkProperties.getHttpProxy());
    368 
    369         checkSetMtu(mApnSetting, result.newLp);
    370 
    371         mLinkProperties = result.newLp;
    372 
    373         updateTcpBufferSizes(mRilRat);
    374 
    375         if (DBG && (! result.oldLp.equals(result.newLp))) {
    376             log("updateLinkProperty old LP=" + result.oldLp);
    377             log("updateLinkProperty new LP=" + result.newLp);
    378         }
    379 
    380         if (result.newLp.equals(result.oldLp) == false &&
    381                 mNetworkAgent != null) {
    382             mNetworkAgent.sendLinkProperties(mLinkProperties);
    383         }
    384 
    385         return result;
    386     }
    387 
    388     /**
    389      * Read the MTU value from link properties where it can be set from network. In case
    390      * not set by the network, set it again using the mtu szie value defined in the APN
    391      * database for the connected APN
    392      */
    393     private void checkSetMtu(ApnSetting apn, LinkProperties lp) {
    394         if (lp == null) return;
    395 
    396         if (apn == null || lp == null) return;
    397 
    398         if (lp.getMtu() != PhoneConstants.UNSET_MTU) {
    399             if (DBG) log("MTU set by call response to: " + lp.getMtu());
    400             return;
    401         }
    402 
    403         if (apn != null && apn.mtu != PhoneConstants.UNSET_MTU) {
    404             lp.setMtu(apn.mtu);
    405             if (DBG) log("MTU set by APN to: " + apn.mtu);
    406             return;
    407         }
    408 
    409         int mtu = mPhone.getContext().getResources().getInteger(
    410                 com.android.internal.R.integer.config_mobile_mtu);
    411         if (mtu != PhoneConstants.UNSET_MTU) {
    412             lp.setMtu(mtu);
    413             if (DBG) log("MTU set by config resource to: " + mtu);
    414         }
    415     }
    416 
    417     //***** Constructor (NOTE: uses dcc.getHandler() as its Handler)
    418     private DataConnection(PhoneBase phone, String name, int id,
    419                 DcTrackerBase dct, DcTesterFailBringUpAll failBringUpAll,
    420                 DcController dcc) {
    421         super(name, dcc.getHandler());
    422         setLogRecSize(300);
    423         setLogOnlyTransitions(true);
    424         if (DBG) log("DataConnection constructor E");
    425 
    426         mPhone = phone;
    427         mDct = dct;
    428         mDcTesterFailBringUpAll = failBringUpAll;
    429         mDcController = dcc;
    430         mId = id;
    431         mCid = -1;
    432         mDcRetryAlarmController = new DcRetryAlarmController(mPhone, this);
    433         ServiceState ss = mPhone.getServiceState();
    434         mRilRat = ss.getRilDataRadioTechnology();
    435         mDataRegState = mPhone.getServiceState().getDataRegState();
    436         int networkType = ss.getDataNetworkType();
    437         mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_MOBILE,
    438                 networkType, NETWORK_TYPE, TelephonyManager.getNetworkTypeName(networkType));
    439         mNetworkInfo.setRoaming(ss.getDataRoaming());
    440         mNetworkInfo.setIsAvailable(true);
    441 
    442         addState(mDefaultState);
    443             addState(mInactiveState, mDefaultState);
    444             addState(mActivatingState, mDefaultState);
    445             addState(mRetryingState, mDefaultState);
    446             addState(mActiveState, mDefaultState);
    447             addState(mDisconnectingState, mDefaultState);
    448             addState(mDisconnectingErrorCreatingConnection, mDefaultState);
    449         setInitialState(mInactiveState);
    450 
    451         mApnContexts = new ArrayList<ApnContext>();
    452         if (DBG) log("DataConnection constructor X");
    453     }
    454 
    455     private String getRetryConfig(boolean forDefault) {
    456         int nt = mPhone.getServiceState().getNetworkType();
    457 
    458         if (Build.IS_DEBUGGABLE) {
    459             String config = SystemProperties.get("test.data_retry_config");
    460             if (! TextUtils.isEmpty(config)) {
    461                 return config;
    462             }
    463         }
    464 
    465         if ((nt == TelephonyManager.NETWORK_TYPE_CDMA) ||
    466             (nt == TelephonyManager.NETWORK_TYPE_1xRTT) ||
    467             (nt == TelephonyManager.NETWORK_TYPE_EVDO_0) ||
    468             (nt == TelephonyManager.NETWORK_TYPE_EVDO_A) ||
    469             (nt == TelephonyManager.NETWORK_TYPE_EVDO_B) ||
    470             (nt == TelephonyManager.NETWORK_TYPE_EHRPD)) {
    471             // CDMA variant
    472             return SystemProperties.get("ro.cdma.data_retry_config");
    473         } else {
    474             // Use GSM variant for all others.
    475             if (forDefault) {
    476                 return SystemProperties.get("ro.gsm.data_retry_config");
    477             } else {
    478                 return SystemProperties.get("ro.gsm.2nd_data_retry_config");
    479             }
    480         }
    481     }
    482 
    483     private void configureRetry(boolean forDefault) {
    484         String retryConfig = getRetryConfig(forDefault);
    485 
    486         if (!mRetryManager.configure(retryConfig)) {
    487             if (forDefault) {
    488                 if (!mRetryManager.configure(DEFAULT_DATA_RETRY_CONFIG)) {
    489                     // Should never happen, log an error and default to a simple linear sequence.
    490                     loge("configureRetry: Could not configure using " +
    491                             "DEFAULT_DATA_RETRY_CONFIG=" + DEFAULT_DATA_RETRY_CONFIG);
    492                     mRetryManager.configure(5, 2000, 1000);
    493                 }
    494             } else {
    495                 if (!mRetryManager.configure(SECONDARY_DATA_RETRY_CONFIG)) {
    496                     // Should never happen, log an error and default to a simple sequence.
    497                     loge("configureRetry: Could note configure using " +
    498                             "SECONDARY_DATA_RETRY_CONFIG=" + SECONDARY_DATA_RETRY_CONFIG);
    499                     mRetryManager.configure(5, 2000, 1000);
    500                 }
    501             }
    502         }
    503         if (DBG) {
    504             log("configureRetry: forDefault=" + forDefault + " mRetryManager=" + mRetryManager);
    505         }
    506     }
    507 
    508     /**
    509      * Begin setting up a data connection, calls setupDataCall
    510      * and the ConnectionParams will be returned with the
    511      * EVENT_SETUP_DATA_CONNECTION_DONE AsyncResul.userObj.
    512      *
    513      * @param cp is the connection parameters
    514      */
    515     private void onConnect(ConnectionParams cp) {
    516         if (DBG) log("onConnect: carrier='" + mApnSetting.carrier
    517                 + "' APN='" + mApnSetting.apn
    518                 + "' proxy='" + mApnSetting.proxy + "' port='" + mApnSetting.port + "'");
    519         if (cp.mApnContext != null) cp.mApnContext.requestLog("DataConnection.onConnect");
    520 
    521         // Check if we should fake an error.
    522         if (mDcTesterFailBringUpAll.getDcFailBringUp().mCounter  > 0) {
    523             DataCallResponse response = new DataCallResponse();
    524             response.version = mPhone.mCi.getRilVersion();
    525             response.status = mDcTesterFailBringUpAll.getDcFailBringUp().mFailCause.getErrorCode();
    526             response.cid = 0;
    527             response.active = 0;
    528             response.type = "";
    529             response.ifname = "";
    530             response.addresses = new String[0];
    531             response.dnses = new String[0];
    532             response.gateways = new String[0];
    533             response.suggestedRetryTime =
    534                     mDcTesterFailBringUpAll.getDcFailBringUp().mSuggestedRetryTime;
    535             response.pcscf = new String[0];
    536             response.mtu = PhoneConstants.UNSET_MTU;
    537 
    538             Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
    539             AsyncResult.forMessage(msg, response, null);
    540             sendMessage(msg);
    541             if (DBG) {
    542                 log("onConnect: FailBringUpAll=" + mDcTesterFailBringUpAll.getDcFailBringUp()
    543                         + " send error response=" + response);
    544             }
    545             mDcTesterFailBringUpAll.getDcFailBringUp().mCounter -= 1;
    546             return;
    547         }
    548 
    549         mCreateTime = -1;
    550         mLastFailTime = -1;
    551         mLastFailCause = DcFailCause.NONE;
    552 
    553         // msg.obj will be returned in AsyncResult.userObj;
    554         Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
    555         msg.obj = cp;
    556 
    557         int authType = mApnSetting.authType;
    558         if (authType == -1) {
    559             authType = TextUtils.isEmpty(mApnSetting.user) ? RILConstants.SETUP_DATA_AUTH_NONE
    560                     : RILConstants.SETUP_DATA_AUTH_PAP_CHAP;
    561         }
    562 
    563         String protocol;
    564         if (mPhone.getServiceState().getDataRoamingFromRegistration()) {
    565             protocol = mApnSetting.roamingProtocol;
    566         } else {
    567             protocol = mApnSetting.protocol;
    568         }
    569 
    570         mPhone.mCi.setupDataCall(
    571                 Integer.toString(cp.mRilRat + 2),
    572                 Integer.toString(cp.mProfileId),
    573                 mApnSetting.apn, mApnSetting.user, mApnSetting.password,
    574                 Integer.toString(authType),
    575                 protocol, msg);
    576     }
    577 
    578     /**
    579      * TearDown the data connection when the deactivation is complete a Message with
    580      * msg.what == EVENT_DEACTIVATE_DONE and msg.obj == AsyncResult with AsyncResult.obj
    581      * containing the parameter o.
    582      *
    583      * @param o is the object returned in the AsyncResult.obj.
    584      */
    585     private void tearDownData(Object o) {
    586         int discReason = RILConstants.DEACTIVATE_REASON_NONE;
    587         ApnContext apnContext = null;
    588         if ((o != null) && (o instanceof DisconnectParams)) {
    589             DisconnectParams dp = (DisconnectParams)o;
    590             apnContext = dp.mApnContext;
    591             if (TextUtils.equals(dp.mReason, Phone.REASON_RADIO_TURNED_OFF)) {
    592                 discReason = RILConstants.DEACTIVATE_REASON_RADIO_OFF;
    593             } else if (TextUtils.equals(dp.mReason, Phone.REASON_PDP_RESET)) {
    594                 discReason = RILConstants.DEACTIVATE_REASON_PDP_RESET;
    595             }
    596         }
    597         if (mPhone.mCi.getRadioState().isOn()
    598                 || (mPhone.getServiceState().getRilDataRadioTechnology()
    599                         == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN )) {
    600             String str = "tearDownData radio is on, call deactivateDataCall";
    601             if (DBG) log(str);
    602             if (apnContext != null) apnContext.requestLog(str);
    603             mPhone.mCi.deactivateDataCall(mCid, discReason,
    604                     obtainMessage(EVENT_DEACTIVATE_DONE, mTag, 0, o));
    605         } else {
    606             String str = "tearDownData radio is off sendMessage EVENT_DEACTIVATE_DONE immediately";
    607             if (DBG) log(str);
    608             if (apnContext != null) apnContext.requestLog(str);
    609             AsyncResult ar = new AsyncResult(o, null, null);
    610             sendMessage(obtainMessage(EVENT_DEACTIVATE_DONE, mTag, 0, ar));
    611         }
    612     }
    613 
    614     private void notifyAllWithEvent(ApnContext alreadySent, int event, String reason) {
    615         mNetworkInfo.setDetailedState(mNetworkInfo.getDetailedState(), reason,
    616                 mNetworkInfo.getExtraInfo());
    617         for (ApnContext apnContext : mApnContexts) {
    618             if (apnContext == alreadySent) continue;
    619             if (reason != null) apnContext.setReason(reason);
    620             Message msg = mDct.obtainMessage(event, apnContext);
    621             AsyncResult.forMessage(msg);
    622             msg.sendToTarget();
    623         }
    624     }
    625 
    626     private void notifyAllOfConnected(String reason) {
    627         notifyAllWithEvent(null, DctConstants.EVENT_DATA_SETUP_COMPLETE, reason);
    628     }
    629 
    630     private void notifyAllOfDisconnectDcRetrying(String reason) {
    631         notifyAllWithEvent(null, DctConstants.EVENT_DISCONNECT_DC_RETRYING, reason);
    632     }
    633     private void notifyAllDisconnectCompleted(DcFailCause cause) {
    634         notifyAllWithEvent(null, DctConstants.EVENT_DISCONNECT_DONE, cause.toString());
    635     }
    636 
    637 
    638     /**
    639      * Send the connectionCompletedMsg.
    640      *
    641      * @param cp is the ConnectionParams
    642      * @param cause and if no error the cause is DcFailCause.NONE
    643      * @param sendAll is true if all contexts are to be notified
    644      */
    645     private void notifyConnectCompleted(ConnectionParams cp, DcFailCause cause, boolean sendAll) {
    646         ApnContext alreadySent = null;
    647 
    648         if (cp != null && cp.mOnCompletedMsg != null) {
    649             // Get the completed message but only use it once
    650             Message connectionCompletedMsg = cp.mOnCompletedMsg;
    651             cp.mOnCompletedMsg = null;
    652             if (connectionCompletedMsg.obj instanceof ApnContext) {
    653                 alreadySent = (ApnContext)connectionCompletedMsg.obj;
    654             }
    655 
    656             long timeStamp = System.currentTimeMillis();
    657             connectionCompletedMsg.arg1 = mCid;
    658 
    659             if (cause == DcFailCause.NONE) {
    660                 mCreateTime = timeStamp;
    661                 AsyncResult.forMessage(connectionCompletedMsg);
    662             } else {
    663                 mLastFailCause = cause;
    664                 mLastFailTime = timeStamp;
    665 
    666                 // Return message with a Throwable exception to signify an error.
    667                 if (cause == null) cause = DcFailCause.UNKNOWN;
    668                 AsyncResult.forMessage(connectionCompletedMsg, cause,
    669                         new Throwable(cause.toString()));
    670             }
    671             if (DBG) {
    672                 log("notifyConnectCompleted at " + timeStamp + " cause=" + cause
    673                         + " connectionCompletedMsg=" + msgToString(connectionCompletedMsg));
    674             }
    675 
    676             connectionCompletedMsg.sendToTarget();
    677         }
    678         if (sendAll) {
    679             notifyAllWithEvent(alreadySent, DctConstants.EVENT_DATA_SETUP_COMPLETE_ERROR,
    680                     cause.toString());
    681         }
    682     }
    683 
    684     /**
    685      * Send ar.userObj if its a message, which is should be back to originator.
    686      *
    687      * @param dp is the DisconnectParams.
    688      */
    689     private void notifyDisconnectCompleted(DisconnectParams dp, boolean sendAll) {
    690         if (VDBG) log("NotifyDisconnectCompleted");
    691 
    692         ApnContext alreadySent = null;
    693         String reason = null;
    694 
    695         if (dp != null && dp.mOnCompletedMsg != null) {
    696             // Get the completed message but only use it once
    697             Message msg = dp.mOnCompletedMsg;
    698             dp.mOnCompletedMsg = null;
    699             if (msg.obj instanceof ApnContext) {
    700                 alreadySent = (ApnContext)msg.obj;
    701             }
    702             reason = dp.mReason;
    703             if (VDBG) {
    704                 log(String.format("msg=%s msg.obj=%s", msg.toString(),
    705                     ((msg.obj instanceof String) ? (String) msg.obj : "<no-reason>")));
    706             }
    707             AsyncResult.forMessage(msg);
    708             msg.sendToTarget();
    709         }
    710         if (sendAll) {
    711             if (reason == null) {
    712                 reason = DcFailCause.UNKNOWN.toString();
    713             }
    714             notifyAllWithEvent(alreadySent, DctConstants.EVENT_DISCONNECT_DONE, reason);
    715         }
    716         if (DBG) log("NotifyDisconnectCompleted DisconnectParams=" + dp);
    717     }
    718 
    719     /*
    720      * **************************************************************************
    721      * Begin Members and methods owned by DataConnectionTracker but stored
    722      * in a DataConnection because there is one per connection.
    723      * **************************************************************************
    724      */
    725 
    726     /*
    727      * The id is owned by DataConnectionTracker.
    728      */
    729     private int mId;
    730 
    731     /**
    732      * Get the DataConnection ID
    733      */
    734     public int getDataConnectionId() {
    735         return mId;
    736     }
    737 
    738     /*
    739      * **************************************************************************
    740      * End members owned by DataConnectionTracker
    741      * **************************************************************************
    742      */
    743 
    744     /**
    745      * Clear all settings called when entering mInactiveState.
    746      */
    747     private void clearSettings() {
    748         if (DBG) log("clearSettings");
    749 
    750         mCreateTime = -1;
    751         mLastFailTime = -1;
    752         mLastFailCause = DcFailCause.NONE;
    753         mCid = -1;
    754 
    755         mPcscfAddr = new String[5];
    756 
    757         mLinkProperties = new LinkProperties();
    758         mApnContexts.clear();
    759         mApnSetting = null;
    760         mDcFailCause = null;
    761     }
    762 
    763     /**
    764      * Process setup completion.
    765      *
    766      * @param ar is the result
    767      * @return SetupResult.
    768      */
    769     private DataCallResponse.SetupResult onSetupConnectionCompleted(AsyncResult ar) {
    770         DataCallResponse response = (DataCallResponse) ar.result;
    771         ConnectionParams cp = (ConnectionParams) ar.userObj;
    772         DataCallResponse.SetupResult result;
    773 
    774         if (cp.mTag != mTag) {
    775             if (DBG) {
    776                 log("onSetupConnectionCompleted stale cp.tag=" + cp.mTag + ", mtag=" + mTag);
    777             }
    778             result = DataCallResponse.SetupResult.ERR_Stale;
    779         } else if (ar.exception != null) {
    780             if (DBG) {
    781                 log("onSetupConnectionCompleted failed, ar.exception=" + ar.exception +
    782                     " response=" + response);
    783             }
    784 
    785             if (ar.exception instanceof CommandException
    786                     && ((CommandException) (ar.exception)).getCommandError()
    787                     == CommandException.Error.RADIO_NOT_AVAILABLE) {
    788                 result = DataCallResponse.SetupResult.ERR_BadCommand;
    789                 result.mFailCause = DcFailCause.RADIO_NOT_AVAILABLE;
    790             } else if ((response == null) || (response.version < 4)) {
    791                 result = DataCallResponse.SetupResult.ERR_GetLastErrorFromRil;
    792             } else {
    793                 result = DataCallResponse.SetupResult.ERR_RilError;
    794                 result.mFailCause = DcFailCause.fromInt(response.status);
    795             }
    796         } else if (response.status != 0) {
    797             result = DataCallResponse.SetupResult.ERR_RilError;
    798             result.mFailCause = DcFailCause.fromInt(response.status);
    799         } else {
    800             if (DBG) log("onSetupConnectionCompleted received DataCallResponse: " + response);
    801             mCid = response.cid;
    802 
    803             mPcscfAddr = response.pcscf;
    804 
    805             result = updateLinkProperty(response).setupResult;
    806         }
    807 
    808         return result;
    809     }
    810 
    811     private boolean isDnsOk(String[] domainNameServers) {
    812         if (NULL_IP.equals(domainNameServers[0]) && NULL_IP.equals(domainNameServers[1])
    813                 && !mPhone.isDnsCheckDisabled()) {
    814             // Work around a race condition where QMI does not fill in DNS:
    815             // Deactivate PDP and let DataConnectionTracker retry.
    816             // Do not apply the race condition workaround for MMS APN
    817             // if Proxy is an IP-address.
    818             // Otherwise, the default APN will not be restored anymore.
    819             if (!mApnSetting.types[0].equals(PhoneConstants.APN_TYPE_MMS)
    820                 || !isIpAddress(mApnSetting.mmsProxy)) {
    821                 log(String.format(
    822                         "isDnsOk: return false apn.types[0]=%s APN_TYPE_MMS=%s isIpAddress(%s)=%s",
    823                         mApnSetting.types[0], PhoneConstants.APN_TYPE_MMS, mApnSetting.mmsProxy,
    824                         isIpAddress(mApnSetting.mmsProxy)));
    825                 return false;
    826             }
    827         }
    828         return true;
    829     }
    830 
    831     private static final String TCP_BUFFER_SIZES_GPRS = "4092,8760,48000,4096,8760,48000";
    832     private static final String TCP_BUFFER_SIZES_EDGE = "4093,26280,70800,4096,16384,70800";
    833     private static final String TCP_BUFFER_SIZES_UMTS = "58254,349525,1048576,58254,349525,1048576";
    834     private static final String TCP_BUFFER_SIZES_1XRTT= "16384,32768,131072,4096,16384,102400";
    835     private static final String TCP_BUFFER_SIZES_EVDO = "4094,87380,262144,4096,16384,262144";
    836     private static final String TCP_BUFFER_SIZES_EHRPD= "131072,262144,1048576,4096,16384,524288";
    837     private static final String TCP_BUFFER_SIZES_HSDPA= "61167,367002,1101005,8738,52429,262114";
    838     private static final String TCP_BUFFER_SIZES_HSPA = "40778,244668,734003,16777,100663,301990";
    839     private static final String TCP_BUFFER_SIZES_LTE  =
    840             "524288,1048576,2097152,262144,524288,1048576";
    841     private static final String TCP_BUFFER_SIZES_HSPAP= "122334,734003,2202010,32040,192239,576717";
    842 
    843     private void updateTcpBufferSizes(int rilRat) {
    844         String sizes = null;
    845         String ratName = ServiceState.rilRadioTechnologyToString(rilRat).toLowerCase(Locale.ROOT);
    846         // ServiceState gives slightly different names for EVDO tech ("evdo-rev.0" for ex)
    847         // - patch it up:
    848         if (rilRat == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0 ||
    849                 rilRat == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A ||
    850                 rilRat == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B) {
    851             ratName = "evdo";
    852         }
    853 
    854         // in the form: "ratname:rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max"
    855         String[] configOverride = mPhone.getContext().getResources().getStringArray(
    856                 com.android.internal.R.array.config_mobile_tcp_buffers);
    857         for (int i = 0; i < configOverride.length; i++) {
    858             String[] split = configOverride[i].split(":");
    859             if (ratName.equals(split[0]) && split.length == 2) {
    860                 sizes = split[1];
    861                 break;
    862             }
    863         }
    864 
    865         if (sizes == null) {
    866             // no override - use telephony defaults
    867             // doing it this way allows device or carrier to just override the types they
    868             // care about and inherit the defaults for the others.
    869             switch (rilRat) {
    870                 case ServiceState.RIL_RADIO_TECHNOLOGY_GPRS:
    871                     sizes = TCP_BUFFER_SIZES_GPRS;
    872                     break;
    873                 case ServiceState.RIL_RADIO_TECHNOLOGY_EDGE:
    874                     sizes = TCP_BUFFER_SIZES_EDGE;
    875                     break;
    876                 case ServiceState.RIL_RADIO_TECHNOLOGY_UMTS:
    877                     sizes = TCP_BUFFER_SIZES_UMTS;
    878                     break;
    879                 case ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT:
    880                     sizes = TCP_BUFFER_SIZES_1XRTT;
    881                     break;
    882                 case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0:
    883                 case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A:
    884                 case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B:
    885                     sizes = TCP_BUFFER_SIZES_EVDO;
    886                     break;
    887                 case ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD:
    888                     sizes = TCP_BUFFER_SIZES_EHRPD;
    889                     break;
    890                 case ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA:
    891                     sizes = TCP_BUFFER_SIZES_HSDPA;
    892                     break;
    893                 case ServiceState.RIL_RADIO_TECHNOLOGY_HSPA:
    894                 case ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA:
    895                     sizes = TCP_BUFFER_SIZES_HSPA;
    896                     break;
    897                 case ServiceState.RIL_RADIO_TECHNOLOGY_LTE:
    898                     sizes = TCP_BUFFER_SIZES_LTE;
    899                     break;
    900                 case ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP:
    901                     sizes = TCP_BUFFER_SIZES_HSPAP;
    902                     break;
    903                 default:
    904                     // Leave empty - this will let ConnectivityService use the system default.
    905                     break;
    906             }
    907         }
    908         mLinkProperties.setTcpBufferSizes(sizes);
    909     }
    910 
    911     private NetworkCapabilities makeNetworkCapabilities() {
    912         NetworkCapabilities result = new NetworkCapabilities();
    913         result.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
    914 
    915         if (mApnSetting != null) {
    916             for (String type : mApnSetting.types) {
    917                 switch (type) {
    918                     case PhoneConstants.APN_TYPE_ALL: {
    919                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
    920                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
    921                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
    922                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA);
    923                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
    924                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_CBS);
    925                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_IA);
    926                         break;
    927                     }
    928                     case PhoneConstants.APN_TYPE_DEFAULT: {
    929                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
    930                         break;
    931                     }
    932                     case PhoneConstants.APN_TYPE_MMS: {
    933                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
    934                         break;
    935                     }
    936                     case PhoneConstants.APN_TYPE_SUPL: {
    937                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
    938                         break;
    939                     }
    940                     case PhoneConstants.APN_TYPE_DUN: {
    941                         ApnSetting securedDunApn = mDct.fetchDunApn();
    942                         if (securedDunApn == null || securedDunApn.equals(mApnSetting)) {
    943                             result.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
    944                         }
    945                         break;
    946                     }
    947                     case PhoneConstants.APN_TYPE_FOTA: {
    948                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA);
    949                         break;
    950                     }
    951                     case PhoneConstants.APN_TYPE_IMS: {
    952                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
    953                         break;
    954                     }
    955                     case PhoneConstants.APN_TYPE_CBS: {
    956                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_CBS);
    957                         break;
    958                     }
    959                     case PhoneConstants.APN_TYPE_IA: {
    960                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_IA);
    961                         break;
    962                     }
    963                     default:
    964                 }
    965             }
    966             result.maybeMarkCapabilitiesRestricted();
    967         }
    968         int up = 14;
    969         int down = 14;
    970         switch (mRilRat) {
    971             case ServiceState.RIL_RADIO_TECHNOLOGY_GPRS: up = 80; down = 80; break;
    972             case ServiceState.RIL_RADIO_TECHNOLOGY_EDGE: up = 59; down = 236; break;
    973             case ServiceState.RIL_RADIO_TECHNOLOGY_UMTS: up = 384; down = 384; break;
    974             case ServiceState.RIL_RADIO_TECHNOLOGY_IS95A: // fall through
    975             case ServiceState.RIL_RADIO_TECHNOLOGY_IS95B: up = 14; down = 14; break;
    976             case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0: up = 153; down = 2457; break;
    977             case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A: up = 1843; down = 3174; break;
    978             case ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT: up = 100; down = 100; break;
    979             case ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA: up = 2048; down = 14336; break;
    980             case ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA: up = 5898; down = 14336; break;
    981             case ServiceState.RIL_RADIO_TECHNOLOGY_HSPA: up = 5898; down = 14336; break;
    982             case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B: up = 1843; down = 5017; break;
    983             case ServiceState.RIL_RADIO_TECHNOLOGY_LTE: up = 51200; down = 102400; break;
    984             case ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD: up = 153; down = 2516; break;
    985             case ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP: up = 11264; down = 43008; break;
    986             default:
    987         }
    988         result.setLinkUpstreamBandwidthKbps(up);
    989         result.setLinkDownstreamBandwidthKbps(down);
    990 
    991         result.setNetworkSpecifier(Integer.toString(mPhone.getSubId()));
    992 
    993         return result;
    994     }
    995 
    996     private boolean isIpAddress(String address) {
    997         if (address == null) return false;
    998 
    999         return Patterns.IP_ADDRESS.matcher(address).matches();
   1000     }
   1001 
   1002     private DataCallResponse.SetupResult setLinkProperties(DataCallResponse response,
   1003             LinkProperties lp) {
   1004         // Check if system property dns usable
   1005         boolean okToUseSystemPropertyDns = false;
   1006         String propertyPrefix = "net." + response.ifname + ".";
   1007         String dnsServers[] = new String[2];
   1008         dnsServers[0] = SystemProperties.get(propertyPrefix + "dns1");
   1009         dnsServers[1] = SystemProperties.get(propertyPrefix + "dns2");
   1010         okToUseSystemPropertyDns = isDnsOk(dnsServers);
   1011 
   1012         // set link properties based on data call response
   1013         return response.setLinkProperties(lp, okToUseSystemPropertyDns);
   1014     }
   1015 
   1016     /**
   1017      * Initialize connection, this will fail if the
   1018      * apnSettings are not compatible.
   1019      *
   1020      * @param cp the Connection paramemters
   1021      * @return true if initialization was successful.
   1022      */
   1023     private boolean initConnection(ConnectionParams cp) {
   1024         ApnContext apnContext = cp.mApnContext;
   1025         if (mApnSetting == null) {
   1026             // Only change apn setting if it isn't set, it will
   1027             // only NOT be set only if we're in DcInactiveState.
   1028             mApnSetting = apnContext.getApnSetting();
   1029         }
   1030         if (mApnSetting == null || !mApnSetting.canHandleType(apnContext.getApnType())) {
   1031             if (DBG) {
   1032                 log("initConnection: incompatible apnSetting in ConnectionParams cp=" + cp
   1033                         + " dc=" + DataConnection.this);
   1034             }
   1035             return false;
   1036         }
   1037         mTag += 1;
   1038         mConnectionParams = cp;
   1039         mConnectionParams.mTag = mTag;
   1040 
   1041         if (!mApnContexts.contains(apnContext)) {
   1042             mApnContexts.add(apnContext);
   1043         }
   1044         configureRetry(mApnSetting.canHandleType(PhoneConstants.APN_TYPE_DEFAULT));
   1045         mRetryManager.setRetryCount(0);
   1046         mRetryManager.setCurMaxRetryCount(mConnectionParams.mInitialMaxRetry);
   1047         mRetryManager.setRetryForever(false);
   1048 
   1049         if (DBG) {
   1050             log("initConnection: "
   1051                     + " RefCount=" + mApnContexts.size()
   1052                     + " mApnList=" + mApnContexts
   1053                     + " mConnectionParams=" + mConnectionParams);
   1054         }
   1055         return true;
   1056     }
   1057 
   1058     /**
   1059      * The parent state for all other states.
   1060      */
   1061     private class DcDefaultState extends State {
   1062         @Override
   1063         public void enter() {
   1064             if (DBG) log("DcDefaultState: enter");
   1065 
   1066             // Register for DRS or RAT change
   1067             mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(getHandler(),
   1068                     DataConnection.EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED, null);
   1069 
   1070             mPhone.getServiceStateTracker().registerForDataRoamingOn(getHandler(),
   1071                     DataConnection.EVENT_DATA_CONNECTION_ROAM_ON, null);
   1072             mPhone.getServiceStateTracker().registerForDataRoamingOff(getHandler(),
   1073                     DataConnection.EVENT_DATA_CONNECTION_ROAM_OFF, null);
   1074 
   1075             // Add ourselves to the list of data connections
   1076             mDcController.addDc(DataConnection.this);
   1077         }
   1078         @Override
   1079         public void exit() {
   1080             if (DBG) log("DcDefaultState: exit");
   1081 
   1082             // Unregister for DRS or RAT change.
   1083             mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(getHandler());
   1084 
   1085             mPhone.getServiceStateTracker().unregisterForDataRoamingOn(getHandler());
   1086             mPhone.getServiceStateTracker().unregisterForDataRoamingOff(getHandler());
   1087 
   1088             // Remove ourselves from the DC lists
   1089             mDcController.removeDc(DataConnection.this);
   1090 
   1091             if (mAc != null) {
   1092                 mAc.disconnected();
   1093                 mAc = null;
   1094             }
   1095             mDcRetryAlarmController.dispose();
   1096             mDcRetryAlarmController = null;
   1097             mApnContexts = null;
   1098             mReconnectIntent = null;
   1099             mDct = null;
   1100             mApnSetting = null;
   1101             mPhone = null;
   1102             mLinkProperties = null;
   1103             mLastFailCause = null;
   1104             mUserData = null;
   1105             mDcController = null;
   1106             mDcTesterFailBringUpAll = null;
   1107         }
   1108 
   1109         @Override
   1110         public boolean processMessage(Message msg) {
   1111             boolean retVal = HANDLED;
   1112 
   1113             if (VDBG) {
   1114                 log("DcDefault msg=" + getWhatToString(msg.what)
   1115                         + " RefCount=" + mApnContexts.size());
   1116             }
   1117             switch (msg.what) {
   1118                 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
   1119                     if (mAc != null) {
   1120                         if (VDBG) log("Disconnecting to previous connection mAc=" + mAc);
   1121                         mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
   1122                                 AsyncChannel.STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED);
   1123                     } else {
   1124                         mAc = new AsyncChannel();
   1125                         mAc.connected(null, getHandler(), msg.replyTo);
   1126                         if (VDBG) log("DcDefaultState: FULL_CONNECTION reply connected");
   1127                         mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
   1128                                 AsyncChannel.STATUS_SUCCESSFUL, mId, "hi");
   1129                     }
   1130                     break;
   1131                 }
   1132                 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
   1133                     if (DBG) {
   1134                         log("DcDefault: CMD_CHANNEL_DISCONNECTED before quiting call dump");
   1135                         dumpToLog();
   1136                     }
   1137 
   1138                     quit();
   1139                     break;
   1140                 }
   1141                 case DcAsyncChannel.REQ_IS_INACTIVE: {
   1142                     boolean val = getIsInactive();
   1143                     if (VDBG) log("REQ_IS_INACTIVE  isInactive=" + val);
   1144                     mAc.replyToMessage(msg, DcAsyncChannel.RSP_IS_INACTIVE, val ? 1 : 0);
   1145                     break;
   1146                 }
   1147                 case DcAsyncChannel.REQ_GET_CID: {
   1148                     int cid = getCid();
   1149                     if (VDBG) log("REQ_GET_CID  cid=" + cid);
   1150                     mAc.replyToMessage(msg, DcAsyncChannel.RSP_GET_CID, cid);
   1151                     break;
   1152                 }
   1153                 case DcAsyncChannel.REQ_GET_APNSETTING: {
   1154                     ApnSetting apnSetting = getApnSetting();
   1155                     if (VDBG) log("REQ_GET_APNSETTING  mApnSetting=" + apnSetting);
   1156                     mAc.replyToMessage(msg, DcAsyncChannel.RSP_GET_APNSETTING, apnSetting);
   1157                     break;
   1158                 }
   1159                 case DcAsyncChannel.REQ_GET_LINK_PROPERTIES: {
   1160                     LinkProperties lp = getCopyLinkProperties();
   1161                     if (VDBG) log("REQ_GET_LINK_PROPERTIES linkProperties" + lp);
   1162                     mAc.replyToMessage(msg, DcAsyncChannel.RSP_GET_LINK_PROPERTIES, lp);
   1163                     break;
   1164                 }
   1165                 case DcAsyncChannel.REQ_SET_LINK_PROPERTIES_HTTP_PROXY: {
   1166                     ProxyInfo proxy = (ProxyInfo) msg.obj;
   1167                     if (VDBG) log("REQ_SET_LINK_PROPERTIES_HTTP_PROXY proxy=" + proxy);
   1168                     setLinkPropertiesHttpProxy(proxy);
   1169                     mAc.replyToMessage(msg, DcAsyncChannel.RSP_SET_LINK_PROPERTIES_HTTP_PROXY);
   1170                     break;
   1171                 }
   1172                 case DcAsyncChannel.REQ_GET_NETWORK_CAPABILITIES: {
   1173                     NetworkCapabilities nc = getCopyNetworkCapabilities();
   1174                     if (VDBG) log("REQ_GET_NETWORK_CAPABILITIES networkCapabilities" + nc);
   1175                     mAc.replyToMessage(msg, DcAsyncChannel.RSP_GET_NETWORK_CAPABILITIES, nc);
   1176                     break;
   1177                 }
   1178                 case DcAsyncChannel.REQ_RESET:
   1179                     if (VDBG) log("DcDefaultState: msg.what=REQ_RESET");
   1180                     transitionTo(mInactiveState);
   1181                     break;
   1182                 case EVENT_CONNECT:
   1183                     if (DBG) log("DcDefaultState: msg.what=EVENT_CONNECT, fail not expected");
   1184                     ConnectionParams cp = (ConnectionParams) msg.obj;
   1185                     notifyConnectCompleted(cp, DcFailCause.UNKNOWN, false);
   1186                     break;
   1187 
   1188                 case EVENT_DISCONNECT:
   1189                     if (DBG) {
   1190                         log("DcDefaultState deferring msg.what=EVENT_DISCONNECT RefCount="
   1191                                 + mApnContexts.size());
   1192                     }
   1193                     deferMessage(msg);
   1194                     break;
   1195 
   1196                 case EVENT_DISCONNECT_ALL:
   1197                     if (DBG) {
   1198                         log("DcDefaultState deferring msg.what=EVENT_DISCONNECT_ALL RefCount="
   1199                                 + mApnContexts.size());
   1200                     }
   1201                     deferMessage(msg);
   1202                     break;
   1203 
   1204                 case EVENT_TEAR_DOWN_NOW:
   1205                     if (DBG) log("DcDefaultState EVENT_TEAR_DOWN_NOW");
   1206                     mPhone.mCi.deactivateDataCall(mCid, 0,  null);
   1207                     break;
   1208 
   1209                 case EVENT_LOST_CONNECTION:
   1210                     if (DBG) {
   1211                         String s = "DcDefaultState ignore EVENT_LOST_CONNECTION"
   1212                             + " tag=" + msg.arg1 + ":mTag=" + mTag;
   1213                         logAndAddLogRec(s);
   1214                     }
   1215                     break;
   1216 
   1217                 case EVENT_RETRY_CONNECTION:
   1218                     if (DBG) {
   1219                         String s = "DcDefaultState ignore EVENT_RETRY_CONNECTION"
   1220                                 + " tag=" + msg.arg1 + ":mTag=" + mTag;
   1221                         logAndAddLogRec(s);
   1222                     }
   1223                     break;
   1224 
   1225                 case EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED:
   1226                     AsyncResult ar = (AsyncResult)msg.obj;
   1227                     Pair<Integer, Integer> drsRatPair = (Pair<Integer, Integer>)ar.result;
   1228                     mDataRegState = drsRatPair.first;
   1229                     if (mRilRat != drsRatPair.second) {
   1230                         updateTcpBufferSizes(drsRatPair.second);
   1231                     }
   1232                     mRilRat = drsRatPair.second;
   1233                     if (DBG) {
   1234                         log("DcDefaultState: EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED"
   1235                                 + " drs=" + mDataRegState
   1236                                 + " mRilRat=" + mRilRat);
   1237                     }
   1238                     ServiceState ss = mPhone.getServiceState();
   1239                     int networkType = ss.getDataNetworkType();
   1240                     mNetworkInfo.setSubtype(networkType,
   1241                             TelephonyManager.getNetworkTypeName(networkType));
   1242                     if (mNetworkAgent != null) {
   1243                         updateNetworkInfoSuspendState();
   1244                         mNetworkAgent.sendNetworkCapabilities(makeNetworkCapabilities());
   1245                         mNetworkAgent.sendNetworkInfo(mNetworkInfo);
   1246                         mNetworkAgent.sendLinkProperties(mLinkProperties);
   1247                     }
   1248                     break;
   1249 
   1250                 case EVENT_DATA_CONNECTION_ROAM_ON:
   1251                     mNetworkInfo.setRoaming(true);
   1252                     break;
   1253 
   1254                 case EVENT_DATA_CONNECTION_ROAM_OFF:
   1255                     mNetworkInfo.setRoaming(false);
   1256                     break;
   1257 
   1258                 default:
   1259                     if (DBG) {
   1260                         log("DcDefaultState: shouldn't happen but ignore msg.what="
   1261                                 + getWhatToString(msg.what));
   1262                     }
   1263                     break;
   1264             }
   1265 
   1266             return retVal;
   1267         }
   1268     }
   1269 
   1270     private boolean updateNetworkInfoSuspendState() {
   1271         final NetworkInfo.DetailedState oldState = mNetworkInfo.getDetailedState();
   1272 
   1273         // this is only called when we are either connected or suspended.  Decide which.
   1274         if (mNetworkAgent == null) {
   1275             Rlog.e(getName(), "Setting suspend state without a NetworkAgent");
   1276         }
   1277 
   1278         // if we are not in-service change to SUSPENDED
   1279         final ServiceStateTracker sst = mPhone.getServiceStateTracker();
   1280         if (sst.getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
   1281             mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, null, null);
   1282         } else {
   1283             // check for voice call and concurrency issues
   1284             if (sst.isConcurrentVoiceAndDataAllowed() == false) {
   1285                 final CallTracker ct = mPhone.getCallTracker();
   1286                 if (ct.getState() != PhoneConstants.State.IDLE) {
   1287                     mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, null, null);
   1288                     return (oldState != NetworkInfo.DetailedState.SUSPENDED);
   1289                 }
   1290             }
   1291             mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
   1292         }
   1293         return (oldState != mNetworkInfo.getDetailedState());
   1294     }
   1295 
   1296     private DcDefaultState mDefaultState = new DcDefaultState();
   1297 
   1298     /**
   1299      * The state machine is inactive and expects a EVENT_CONNECT.
   1300      */
   1301     private class DcInactiveState extends State {
   1302         // Inform all contexts we've failed connecting
   1303         public void setEnterNotificationParams(ConnectionParams cp, DcFailCause cause) {
   1304             if (VDBG) log("DcInactiveState: setEnterNoticationParams cp,cause");
   1305             mConnectionParams = cp;
   1306             mDisconnectParams = null;
   1307             mDcFailCause = cause;
   1308         }
   1309 
   1310         // Inform all contexts we've failed disconnected
   1311         public void setEnterNotificationParams(DisconnectParams dp) {
   1312             if (VDBG) log("DcInactiveState: setEnterNoticationParams dp");
   1313             mConnectionParams = null;
   1314             mDisconnectParams = dp;
   1315             mDcFailCause = DcFailCause.NONE;
   1316         }
   1317 
   1318         // Inform all contexts of the failure cause
   1319         public void setEnterNotificationParams(DcFailCause cause) {
   1320             mConnectionParams = null;
   1321             mDisconnectParams = null;
   1322             mDcFailCause = cause;
   1323         }
   1324 
   1325         @Override
   1326         public void enter() {
   1327             mTag += 1;
   1328             if (DBG) log("DcInactiveState: enter() mTag=" + mTag);
   1329 
   1330             if (mConnectionParams != null) {
   1331                 if (DBG) {
   1332                     log("DcInactiveState: enter notifyConnectCompleted +ALL failCause="
   1333                             + mDcFailCause);
   1334                 }
   1335                 notifyConnectCompleted(mConnectionParams, mDcFailCause, true);
   1336             }
   1337             if (mDisconnectParams != null) {
   1338                 if (DBG) {
   1339                     log("DcInactiveState: enter notifyDisconnectCompleted +ALL failCause="
   1340                             + mDcFailCause);
   1341                 }
   1342                 notifyDisconnectCompleted(mDisconnectParams, true);
   1343             }
   1344             if (mDisconnectParams == null && mConnectionParams == null && mDcFailCause != null) {
   1345                 if (DBG) {
   1346                     log("DcInactiveState: enter notifyAllDisconnectCompleted failCause="
   1347                             + mDcFailCause);
   1348                 }
   1349                 notifyAllDisconnectCompleted(mDcFailCause);
   1350             }
   1351 
   1352             // Remove ourselves from cid mapping, before clearSettings
   1353             mDcController.removeActiveDcByCid(DataConnection.this);
   1354 
   1355             clearSettings();
   1356         }
   1357 
   1358         @Override
   1359         public void exit() {
   1360         }
   1361 
   1362         @Override
   1363         public boolean processMessage(Message msg) {
   1364             boolean retVal;
   1365 
   1366             switch (msg.what) {
   1367                 case DcAsyncChannel.REQ_RESET:
   1368                     if (DBG) {
   1369                         log("DcInactiveState: msg.what=RSP_RESET, ignore we're already reset");
   1370                     }
   1371                     retVal = HANDLED;
   1372                     break;
   1373 
   1374                 case EVENT_CONNECT:
   1375                     if (DBG) log("DcInactiveState: mag.what=EVENT_CONNECT");
   1376                     ConnectionParams cp = (ConnectionParams) msg.obj;
   1377                     if (initConnection(cp)) {
   1378                         onConnect(mConnectionParams);
   1379                         transitionTo(mActivatingState);
   1380                     } else {
   1381                         if (DBG) {
   1382                             log("DcInactiveState: msg.what=EVENT_CONNECT initConnection failed");
   1383                         }
   1384                         notifyConnectCompleted(cp, DcFailCause.UNACCEPTABLE_NETWORK_PARAMETER,
   1385                                 false);
   1386                     }
   1387                     retVal = HANDLED;
   1388                     break;
   1389 
   1390                 case EVENT_DISCONNECT:
   1391                     if (DBG) log("DcInactiveState: msg.what=EVENT_DISCONNECT");
   1392                     notifyDisconnectCompleted((DisconnectParams)msg.obj, false);
   1393                     retVal = HANDLED;
   1394                     break;
   1395 
   1396                 case EVENT_DISCONNECT_ALL:
   1397                     if (DBG) log("DcInactiveState: msg.what=EVENT_DISCONNECT_ALL");
   1398                     notifyDisconnectCompleted((DisconnectParams)msg.obj, false);
   1399                     retVal = HANDLED;
   1400                     break;
   1401 
   1402                 default:
   1403                     if (VDBG) {
   1404                         log("DcInactiveState nothandled msg.what=" + getWhatToString(msg.what));
   1405                     }
   1406                     retVal = NOT_HANDLED;
   1407                     break;
   1408             }
   1409             return retVal;
   1410         }
   1411     }
   1412     private DcInactiveState mInactiveState = new DcInactiveState();
   1413 
   1414     /**
   1415      * The state machine is retrying and expects a EVENT_RETRY_CONNECTION.
   1416      */
   1417     private class DcRetryingState extends State {
   1418         @Override
   1419         public void enter() {
   1420             if ((mConnectionParams.mRilRat != mRilRat)
   1421                     || (mDataRegState != ServiceState.STATE_IN_SERVICE)){
   1422                 // RAT has changed or we're not in service so don't even begin retrying.
   1423                 if (DBG) {
   1424                     String s = "DcRetryingState: enter() not retrying rat changed"
   1425                         + ", mConnectionParams.mRilRat=" + mConnectionParams.mRilRat
   1426                         + " != mRilRat:" + mRilRat
   1427                         + " transitionTo(mInactiveState)";
   1428                     logAndAddLogRec(s);
   1429                 }
   1430                 mInactiveState.setEnterNotificationParams(DcFailCause.LOST_CONNECTION);
   1431                 transitionTo(mInactiveState);
   1432             } else {
   1433                 if (DBG) {
   1434                     log("DcRetryingState: enter() mTag=" + mTag
   1435                         + ", call notifyAllOfDisconnectDcRetrying lostConnection");
   1436                 }
   1437 
   1438                 notifyAllOfDisconnectDcRetrying(Phone.REASON_LOST_DATA_CONNECTION);
   1439 
   1440                 // Remove ourselves from cid mapping
   1441                 mDcController.removeActiveDcByCid(DataConnection.this);
   1442                 mCid = -1;
   1443             }
   1444         }
   1445 
   1446         @Override
   1447         public boolean processMessage(Message msg) {
   1448             boolean retVal;
   1449 
   1450             switch (msg.what) {
   1451                 case EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED:
   1452                     AsyncResult ar = (AsyncResult)msg.obj;
   1453                     Pair<Integer, Integer> drsRatPair = (Pair<Integer, Integer>)ar.result;
   1454                     int drs = drsRatPair.first;
   1455                     int rat = drsRatPair.second;
   1456                     if ((rat == mRilRat) && (drs == mDataRegState)) {
   1457                         if (DBG) {
   1458                             log("DcRetryingState: EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED"
   1459                                     + " strange no change in drs=" + drs
   1460                                     + " rat=" + rat + " ignoring");
   1461                         }
   1462                     } else {
   1463                         // have to retry connecting since no attach event will come
   1464                         if (mConnectionParams.mRetryWhenSSChange) {
   1465                             retVal = NOT_HANDLED;
   1466                             break;
   1467                         }
   1468                         // We've lost the connection and we're retrying but DRS or RAT changed
   1469                         // so we may never succeed, might as well give up.
   1470                         mInactiveState.setEnterNotificationParams(DcFailCause.LOST_CONNECTION);
   1471                         deferMessage(msg);
   1472                         transitionTo(mInactiveState);
   1473 
   1474                         if (DBG) {
   1475                             String s = "DcRetryingState: EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED"
   1476                                     + " giving up changed from " + mRilRat
   1477                                     + " to rat=" + rat
   1478                                     + " or drs changed from " + mDataRegState + " to drs=" + drs;
   1479                             logAndAddLogRec(s);
   1480                         }
   1481                         mDataRegState = drs;
   1482                         mRilRat = rat;
   1483                         // TODO - pass the other type here too?
   1484                         ServiceState ss = mPhone.getServiceState();
   1485                         int networkType = ss.getDataNetworkType();
   1486                         mNetworkInfo.setSubtype(networkType,
   1487                                 TelephonyManager.getNetworkTypeName(networkType));
   1488                     }
   1489                     retVal = HANDLED;
   1490                     break;
   1491 
   1492                 case EVENT_RETRY_CONNECTION: {
   1493                     if (msg.arg1 == mTag) {
   1494                         mRetryManager.increaseRetryCount();
   1495                         if (DBG) {
   1496                             log("DcRetryingState EVENT_RETRY_CONNECTION"
   1497                                     + " RetryCount=" +  mRetryManager.getRetryCount()
   1498                                     + " mConnectionParams=" + mConnectionParams);
   1499                         }
   1500                         onConnect(mConnectionParams);
   1501                         transitionTo(mActivatingState);
   1502                     } else {
   1503                         if (DBG) {
   1504                             log("DcRetryingState stale EVENT_RETRY_CONNECTION"
   1505                                     + " tag:" + msg.arg1 + " != mTag:" + mTag);
   1506                         }
   1507                     }
   1508                     retVal = HANDLED;
   1509                     break;
   1510                 }
   1511                 case DcAsyncChannel.REQ_RESET: {
   1512                     if (DBG) {
   1513                         log("DcRetryingState: msg.what=RSP_RESET, ignore we're already reset");
   1514                     }
   1515                     mInactiveState.setEnterNotificationParams(mConnectionParams,
   1516                             DcFailCause.RESET_BY_FRAMEWORK);
   1517                     transitionTo(mInactiveState);
   1518                     retVal = HANDLED;
   1519                     break;
   1520                 }
   1521                 case EVENT_CONNECT: {
   1522                     ConnectionParams cp = (ConnectionParams) msg.obj;
   1523                     if (DBG) {
   1524                         log("DcRetryingState: msg.what=EVENT_CONNECT"
   1525                                 + " RefCount=" + mApnContexts.size() + " cp=" + cp
   1526                                 + " mConnectionParams=" + mConnectionParams);
   1527                     }
   1528                     if (initConnection(cp)) {
   1529                         onConnect(mConnectionParams);
   1530                         transitionTo(mActivatingState);
   1531                     } else {
   1532                         if (DBG) {
   1533                             log("DcRetryingState: msg.what=EVENT_CONNECT initConnection failed");
   1534                         }
   1535                         notifyConnectCompleted(cp, DcFailCause.UNACCEPTABLE_NETWORK_PARAMETER,
   1536                                 false);
   1537                     }
   1538                     retVal = HANDLED;
   1539                     break;
   1540                 }
   1541                 case EVENT_DISCONNECT: {
   1542                     DisconnectParams dp = (DisconnectParams) msg.obj;
   1543 
   1544                     if (mApnContexts.remove(dp.mApnContext) && mApnContexts.size() == 0) {
   1545                         if (DBG) {
   1546                             log("DcRetryingState msg.what=EVENT_DISCONNECT " + " RefCount="
   1547                                     + mApnContexts.size() + " dp=" + dp);
   1548                         }
   1549                         mInactiveState.setEnterNotificationParams(dp);
   1550                         transitionTo(mInactiveState);
   1551                     } else {
   1552                         if (DBG) log("DcRetryingState: msg.what=EVENT_DISCONNECT");
   1553                         notifyDisconnectCompleted(dp, false);
   1554                     }
   1555                     retVal = HANDLED;
   1556                     break;
   1557                 }
   1558                 case EVENT_DISCONNECT_ALL: {
   1559                     if (DBG) {
   1560                         log("DcRetryingState msg.what=EVENT_DISCONNECT/DISCONNECT_ALL "
   1561                                 + "RefCount=" + mApnContexts.size());
   1562                     }
   1563                     mInactiveState.setEnterNotificationParams(DcFailCause.LOST_CONNECTION);
   1564                     transitionTo(mInactiveState);
   1565                     retVal = HANDLED;
   1566                     break;
   1567                 }
   1568                 default: {
   1569                     if (VDBG) {
   1570                         log("DcRetryingState nothandled msg.what=" + getWhatToString(msg.what));
   1571                     }
   1572                     retVal = NOT_HANDLED;
   1573                     break;
   1574                 }
   1575             }
   1576             return retVal;
   1577         }
   1578     }
   1579     private DcRetryingState mRetryingState = new DcRetryingState();
   1580 
   1581     /**
   1582      * The state machine is activating a connection.
   1583      */
   1584     private class DcActivatingState extends State {
   1585         @Override
   1586         public boolean processMessage(Message msg) {
   1587             boolean retVal;
   1588             AsyncResult ar;
   1589             ConnectionParams cp;
   1590 
   1591             if (DBG) log("DcActivatingState: msg=" + msgToString(msg));
   1592             switch (msg.what) {
   1593                 case EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED:
   1594                 case EVENT_CONNECT:
   1595                     // Activating can't process until we're done.
   1596                     deferMessage(msg);
   1597                     retVal = HANDLED;
   1598                     break;
   1599 
   1600                 case EVENT_SETUP_DATA_CONNECTION_DONE:
   1601                     ar = (AsyncResult) msg.obj;
   1602                     cp = (ConnectionParams) ar.userObj;
   1603 
   1604                     DataCallResponse.SetupResult result = onSetupConnectionCompleted(ar);
   1605                     if (result != DataCallResponse.SetupResult.ERR_Stale) {
   1606                         if (mConnectionParams != cp) {
   1607                             loge("DcActivatingState: WEIRD mConnectionsParams:"+ mConnectionParams
   1608                                     + " != cp:" + cp);
   1609                         }
   1610                     }
   1611                     if (DBG) {
   1612                         log("DcActivatingState onSetupConnectionCompleted result=" + result
   1613                                 + " dc=" + DataConnection.this);
   1614                     }
   1615                     if (cp.mApnContext != null) {
   1616                         cp.mApnContext.requestLog("onSetupConnectionCompleted result=" + result);
   1617                     }
   1618                     switch (result) {
   1619                         case SUCCESS:
   1620                             // All is well
   1621                             mDcFailCause = DcFailCause.NONE;
   1622                             transitionTo(mActiveState);
   1623                             break;
   1624                         case ERR_BadCommand:
   1625                             // Vendor ril rejected the command and didn't connect.
   1626                             // Transition to inactive but send notifications after
   1627                             // we've entered the mInactive state.
   1628                             mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
   1629                             transitionTo(mInactiveState);
   1630                             break;
   1631                         case ERR_UnacceptableParameter:
   1632                             // The addresses given from the RIL are bad
   1633                             tearDownData(cp);
   1634                             transitionTo(mDisconnectingErrorCreatingConnection);
   1635                             break;
   1636                         case ERR_GetLastErrorFromRil:
   1637                             // Request failed and this is an old RIL
   1638                             mPhone.mCi.getLastDataCallFailCause(
   1639                                     obtainMessage(EVENT_GET_LAST_FAIL_DONE, cp));
   1640                             break;
   1641                         case ERR_RilError:
   1642                             int delay = mDcRetryAlarmController.getSuggestedRetryTime(
   1643                                                                     DataConnection.this, ar);
   1644                             String str = "DcActivatingState: ERR_RilError "
   1645                                     + " delay=" + delay
   1646                                     + " isRetryNeeded=" + mRetryManager.isRetryNeeded()
   1647                                     + " result=" + result
   1648                                     + " result.isRestartRadioFail=" +
   1649                                     result.mFailCause.isRestartRadioFail()
   1650                                     + " result.isPermanentFail=" +
   1651                                     mDct.isPermanentFail(result.mFailCause);
   1652                             if (DBG) log(str);
   1653                             if (cp.mApnContext != null) cp.mApnContext.requestLog(str);
   1654                             if (result.mFailCause.isRestartRadioFail() ||
   1655                                     (cp.mApnContext != null &&
   1656                                     cp.mApnContext.restartOnError(
   1657                                     result.mFailCause.getErrorCode()))) {
   1658                                 if (DBG) log("DcActivatingState: ERR_RilError restart radio");
   1659                                 mDct.sendRestartRadio();
   1660                                 mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
   1661                                 transitionTo(mInactiveState);
   1662                             } else if (mDct.isPermanentFail(result.mFailCause)) {
   1663                                 if (DBG) log("DcActivatingState: ERR_RilError perm error");
   1664                                 mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
   1665                                 transitionTo(mInactiveState);
   1666                             } else if (delay >= 0) {
   1667                                 if (DBG) log("DcActivatingState: ERR_RilError retry");
   1668                                 mDcRetryAlarmController.startRetryAlarm(EVENT_RETRY_CONNECTION,
   1669                                                             mTag, delay);
   1670                                 transitionTo(mRetryingState);
   1671                             } else {
   1672                                 if (DBG) log("DcActivatingState: ERR_RilError no retry");
   1673                                 mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
   1674                                 transitionTo(mInactiveState);
   1675                             }
   1676                             break;
   1677                         case ERR_Stale:
   1678                             loge("DcActivatingState: stale EVENT_SETUP_DATA_CONNECTION_DONE"
   1679                                     + " tag:" + cp.mTag + " != mTag:" + mTag);
   1680                             break;
   1681                         default:
   1682                             throw new RuntimeException("Unknown SetupResult, should not happen");
   1683                     }
   1684                     retVal = HANDLED;
   1685                     break;
   1686 
   1687                 case EVENT_GET_LAST_FAIL_DONE:
   1688                     ar = (AsyncResult) msg.obj;
   1689                     cp = (ConnectionParams) ar.userObj;
   1690                     if (cp.mTag == mTag) {
   1691                         if (mConnectionParams != cp) {
   1692                             loge("DcActivatingState: WEIRD mConnectionsParams:" + mConnectionParams
   1693                                     + " != cp:" + cp);
   1694                         }
   1695 
   1696                         DcFailCause cause = DcFailCause.UNKNOWN;
   1697 
   1698                         if (ar.exception == null) {
   1699                             int rilFailCause = ((int[]) (ar.result))[0];
   1700                             cause = DcFailCause.fromInt(rilFailCause);
   1701                             if (cause == DcFailCause.NONE) {
   1702                                 if (DBG) {
   1703                                     log("DcActivatingState msg.what=EVENT_GET_LAST_FAIL_DONE"
   1704                                             + " BAD: error was NONE, change to UNKNOWN");
   1705                                 }
   1706                                 cause = DcFailCause.UNKNOWN;
   1707                             }
   1708                         }
   1709                         mDcFailCause = cause;
   1710 
   1711                         int retryDelay = mRetryManager.getRetryTimer();
   1712                         if (DBG) {
   1713                             log("DcActivatingState msg.what=EVENT_GET_LAST_FAIL_DONE"
   1714                                     + " cause=" + cause
   1715                                     + " retryDelay=" + retryDelay
   1716                                     + " isRetryNeeded=" + mRetryManager.isRetryNeeded()
   1717                                     + " dc=" + DataConnection.this);
   1718                         }
   1719                         if (cause.isRestartRadioFail()) {
   1720                             if (DBG) {
   1721                                 log("DcActivatingState: EVENT_GET_LAST_FAIL_DONE"
   1722                                         + " restart radio");
   1723                             }
   1724                             mDct.sendRestartRadio();
   1725                             mInactiveState.setEnterNotificationParams(cp, cause);
   1726                             transitionTo(mInactiveState);
   1727                         } else if (mDct.isPermanentFail(cause)) {
   1728                             if (DBG) log("DcActivatingState: EVENT_GET_LAST_FAIL_DONE perm er");
   1729                             mInactiveState.setEnterNotificationParams(cp, cause);
   1730                             transitionTo(mInactiveState);
   1731                         } else if ((retryDelay >= 0) && (mRetryManager.isRetryNeeded())) {
   1732                             if (DBG) log("DcActivatingState: EVENT_GET_LAST_FAIL_DONE retry");
   1733                             mDcRetryAlarmController.startRetryAlarm(EVENT_RETRY_CONNECTION, mTag,
   1734                                                             retryDelay);
   1735                             transitionTo(mRetryingState);
   1736                         } else {
   1737                             if (DBG) log("DcActivatingState: EVENT_GET_LAST_FAIL_DONE no retry");
   1738                             mInactiveState.setEnterNotificationParams(cp, cause);
   1739                             transitionTo(mInactiveState);
   1740                         }
   1741                     } else {
   1742                         loge("DcActivatingState: stale EVENT_GET_LAST_FAIL_DONE"
   1743                                 + " tag:" + cp.mTag + " != mTag:" + mTag);
   1744                     }
   1745 
   1746                     retVal = HANDLED;
   1747                     break;
   1748 
   1749                 default:
   1750                     if (VDBG) {
   1751                         log("DcActivatingState not handled msg.what=" +
   1752                                 getWhatToString(msg.what) + " RefCount=" + mApnContexts.size());
   1753                     }
   1754                     retVal = NOT_HANDLED;
   1755                     break;
   1756             }
   1757             return retVal;
   1758         }
   1759     }
   1760     private DcActivatingState mActivatingState = new DcActivatingState();
   1761 
   1762     /**
   1763      * The state machine is connected, expecting an EVENT_DISCONNECT.
   1764      */
   1765     private class DcActiveState extends State {
   1766         @Override public void enter() {
   1767             if (DBG) log("DcActiveState: enter dc=" + DataConnection.this);
   1768 
   1769             if (mRetryManager.getRetryCount() != 0) {
   1770                 log("DcActiveState: connected after retrying call notifyAllOfConnected");
   1771                 mRetryManager.setRetryCount(0);
   1772             }
   1773             // If we were retrying there maybe more than one, otherwise they'll only be one.
   1774             notifyAllOfConnected(Phone.REASON_CONNECTED);
   1775 
   1776             mPhone.getCallTracker().registerForVoiceCallStarted(getHandler(),
   1777                     DataConnection.EVENT_DATA_CONNECTION_VOICE_CALL_STARTED, null);
   1778             mPhone.getCallTracker().registerForVoiceCallEnded(getHandler(),
   1779                     DataConnection.EVENT_DATA_CONNECTION_VOICE_CALL_ENDED, null);
   1780 
   1781             // If the EVENT_CONNECT set the current max retry restore it here
   1782             // if it didn't then this is effectively a NOP.
   1783             mRetryManager.restoreCurMaxRetryCount();
   1784             mDcController.addActiveDcByCid(DataConnection.this);
   1785 
   1786             mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED,
   1787                     mNetworkInfo.getReason(), null);
   1788             mNetworkInfo.setExtraInfo(mApnSetting.apn);
   1789             updateTcpBufferSizes(mRilRat);
   1790 
   1791             final NetworkMisc misc = new NetworkMisc();
   1792             misc.subscriberId = mPhone.getSubscriberId();
   1793             mNetworkAgent = new DcNetworkAgent(getHandler().getLooper(), mPhone.getContext(),
   1794                     "DcNetworkAgent", mNetworkInfo, makeNetworkCapabilities(), mLinkProperties,
   1795                     50, misc);
   1796         }
   1797 
   1798         @Override
   1799         public void exit() {
   1800             if (DBG) log("DcActiveState: exit dc=" + this);
   1801             String reason = mNetworkInfo.getReason();
   1802             if(mDcController.isExecutingCarrierChange()) {
   1803                 reason = Phone.REASON_CARRIER_CHANGE;
   1804             } else if (mDisconnectParams != null && mDisconnectParams.mReason != null) {
   1805                 reason = mDisconnectParams.mReason;
   1806             } else if (mDcFailCause != null) {
   1807                 reason = mDcFailCause.toString();
   1808             }
   1809             mPhone.getCallTracker().unregisterForVoiceCallStarted(getHandler());
   1810             mPhone.getCallTracker().unregisterForVoiceCallEnded(getHandler());
   1811 
   1812             mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
   1813                     reason, mNetworkInfo.getExtraInfo());
   1814             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
   1815             mNetworkAgent = null;
   1816         }
   1817 
   1818         @Override
   1819         public boolean processMessage(Message msg) {
   1820             boolean retVal;
   1821 
   1822             switch (msg.what) {
   1823                 case EVENT_CONNECT: {
   1824                     ConnectionParams cp = (ConnectionParams) msg.obj;
   1825                     if (DBG) {
   1826                         log("DcActiveState: EVENT_CONNECT cp=" + cp + " dc=" + DataConnection.this);
   1827                     }
   1828                     if (mApnContexts.contains(cp.mApnContext)) {
   1829                         log("DcActiveState ERROR already added apnContext=" + cp.mApnContext);
   1830                     } else {
   1831                         mApnContexts.add(cp.mApnContext);
   1832                         if (DBG) {
   1833                             log("DcActiveState msg.what=EVENT_CONNECT RefCount="
   1834                                     + mApnContexts.size());
   1835                         }
   1836                     }
   1837                     notifyConnectCompleted(cp, DcFailCause.NONE, false);
   1838                     retVal = HANDLED;
   1839                     break;
   1840                 }
   1841                 case EVENT_DISCONNECT: {
   1842                     DisconnectParams dp = (DisconnectParams) msg.obj;
   1843                     if (DBG) {
   1844                         log("DcActiveState: EVENT_DISCONNECT dp=" + dp
   1845                                 + " dc=" + DataConnection.this);
   1846                     }
   1847                     if (mApnContexts.contains(dp.mApnContext)) {
   1848                         if (DBG) {
   1849                             log("DcActiveState msg.what=EVENT_DISCONNECT RefCount="
   1850                                     + mApnContexts.size());
   1851                         }
   1852 
   1853                         if (mApnContexts.size() == 1) {
   1854                             mApnContexts.clear();
   1855                             mDisconnectParams = dp;
   1856                             mConnectionParams = null;
   1857                             dp.mTag = mTag;
   1858                             tearDownData(dp);
   1859                             transitionTo(mDisconnectingState);
   1860                         } else {
   1861                             mApnContexts.remove(dp.mApnContext);
   1862                             notifyDisconnectCompleted(dp, false);
   1863                         }
   1864                     } else {
   1865                         log("DcActiveState ERROR no such apnContext=" + dp.mApnContext
   1866                                 + " in this dc=" + DataConnection.this);
   1867                         notifyDisconnectCompleted(dp, false);
   1868                     }
   1869                     retVal = HANDLED;
   1870                     break;
   1871                 }
   1872                 case EVENT_DISCONNECT_ALL: {
   1873                     if (DBG) {
   1874                         log("DcActiveState EVENT_DISCONNECT clearing apn contexts,"
   1875                                 + " dc=" + DataConnection.this);
   1876                     }
   1877                     DisconnectParams dp = (DisconnectParams) msg.obj;
   1878                     mDisconnectParams = dp;
   1879                     mConnectionParams = null;
   1880                     dp.mTag = mTag;
   1881                     tearDownData(dp);
   1882                     transitionTo(mDisconnectingState);
   1883                     retVal = HANDLED;
   1884                     break;
   1885                 }
   1886                 case EVENT_LOST_CONNECTION: {
   1887                     if (DBG) {
   1888                         log("DcActiveState EVENT_LOST_CONNECTION dc=" + DataConnection.this);
   1889                     }
   1890                     if (mRetryManager.isRetryNeeded()) {
   1891                         // We're going to retry
   1892                         int delayMillis = mRetryManager.getRetryTimer();
   1893                         if (DBG) {
   1894                             log("DcActiveState EVENT_LOST_CONNECTION startRetryAlarm"
   1895                                     + " mTag=" + mTag + " delay=" + delayMillis + "ms");
   1896                         }
   1897                         mDcRetryAlarmController.startRetryAlarm(EVENT_RETRY_CONNECTION, mTag,
   1898                                 delayMillis);
   1899                         transitionTo(mRetryingState);
   1900                     } else {
   1901                         mInactiveState.setEnterNotificationParams(DcFailCause.LOST_CONNECTION);
   1902                         transitionTo(mInactiveState);
   1903                     }
   1904                     retVal = HANDLED;
   1905                     break;
   1906                 }
   1907                 case EVENT_DATA_CONNECTION_ROAM_ON: {
   1908                     mNetworkInfo.setRoaming(true);
   1909                     mNetworkAgent.sendNetworkInfo(mNetworkInfo);
   1910                     retVal = HANDLED;
   1911                     break;
   1912                 }
   1913                 case EVENT_DATA_CONNECTION_ROAM_OFF: {
   1914                     mNetworkInfo.setRoaming(false);
   1915                     mNetworkAgent.sendNetworkInfo(mNetworkInfo);
   1916                     retVal = HANDLED;
   1917                     break;
   1918                 }
   1919                 case EVENT_BW_REFRESH_RESPONSE: {
   1920                     AsyncResult ar = (AsyncResult)msg.obj;
   1921                     if (ar.exception != null) {
   1922                         log("EVENT_BW_REFRESH_RESPONSE: error ignoring, e=" + ar.exception);
   1923                     } else {
   1924                         final ArrayList<Integer> capInfo = (ArrayList<Integer>)ar.result;
   1925                         final int lceBwDownKbps = capInfo.get(0);
   1926                         NetworkCapabilities nc = makeNetworkCapabilities();
   1927                         if (mPhone.getLceStatus() == RILConstants.LCE_ACTIVE) {
   1928                             nc.setLinkDownstreamBandwidthKbps(lceBwDownKbps);
   1929                             if (mNetworkAgent != null) {
   1930                                 mNetworkAgent.sendNetworkCapabilities(nc);
   1931                             }
   1932                         }
   1933                     }
   1934                     retVal = HANDLED;
   1935                     break;
   1936                 }
   1937                 case EVENT_DATA_CONNECTION_VOICE_CALL_STARTED:
   1938                 case EVENT_DATA_CONNECTION_VOICE_CALL_ENDED: {
   1939                     if (updateNetworkInfoSuspendState()) {
   1940                         // state changed
   1941                         mNetworkAgent.sendNetworkInfo(mNetworkInfo);
   1942                     }
   1943                     retVal = HANDLED;
   1944                     break;
   1945                 }
   1946                 default:
   1947                     if (VDBG) {
   1948                         log("DcActiveState not handled msg.what=" + getWhatToString(msg.what));
   1949                     }
   1950                     retVal = NOT_HANDLED;
   1951                     break;
   1952             }
   1953             return retVal;
   1954         }
   1955     }
   1956     private DcActiveState mActiveState = new DcActiveState();
   1957 
   1958     /**
   1959      * The state machine is disconnecting.
   1960      */
   1961     private class DcDisconnectingState extends State {
   1962         @Override
   1963         public boolean processMessage(Message msg) {
   1964             boolean retVal;
   1965 
   1966             switch (msg.what) {
   1967                 case EVENT_CONNECT:
   1968                     if (DBG) log("DcDisconnectingState msg.what=EVENT_CONNECT. Defer. RefCount = "
   1969                             + mApnContexts.size());
   1970                     deferMessage(msg);
   1971                     retVal = HANDLED;
   1972                     break;
   1973 
   1974                 case EVENT_DEACTIVATE_DONE:
   1975                     AsyncResult ar = (AsyncResult) msg.obj;
   1976                     DisconnectParams dp = (DisconnectParams) ar.userObj;
   1977 
   1978                     String str = "DcDisconnectingState msg.what=EVENT_DEACTIVATE_DONE RefCount="
   1979                             + mApnContexts.size();
   1980                     if (DBG) log(str);
   1981                     if (dp.mApnContext != null) dp.mApnContext.requestLog(str);
   1982 
   1983                     if (dp.mTag == mTag) {
   1984                         // Transition to inactive but send notifications after
   1985                         // we've entered the mInactive state.
   1986                         mInactiveState.setEnterNotificationParams((DisconnectParams) ar.userObj);
   1987                         transitionTo(mInactiveState);
   1988                     } else {
   1989                         if (DBG) log("DcDisconnectState stale EVENT_DEACTIVATE_DONE"
   1990                                 + " dp.tag=" + dp.mTag + " mTag=" + mTag);
   1991                     }
   1992                     retVal = HANDLED;
   1993                     break;
   1994 
   1995                 default:
   1996                     if (VDBG) {
   1997                         log("DcDisconnectingState not handled msg.what="
   1998                                 + getWhatToString(msg.what));
   1999                     }
   2000                     retVal = NOT_HANDLED;
   2001                     break;
   2002             }
   2003             return retVal;
   2004         }
   2005     }
   2006     private DcDisconnectingState mDisconnectingState = new DcDisconnectingState();
   2007 
   2008     /**
   2009      * The state machine is disconnecting after an creating a connection.
   2010      */
   2011     private class DcDisconnectionErrorCreatingConnection extends State {
   2012         @Override
   2013         public boolean processMessage(Message msg) {
   2014             boolean retVal;
   2015 
   2016             switch (msg.what) {
   2017                 case EVENT_DEACTIVATE_DONE:
   2018                     AsyncResult ar = (AsyncResult) msg.obj;
   2019                     ConnectionParams cp = (ConnectionParams) ar.userObj;
   2020                     if (cp.mTag == mTag) {
   2021                         String str = "DcDisconnectionErrorCreatingConnection" +
   2022                                 " msg.what=EVENT_DEACTIVATE_DONE";
   2023                         if (DBG) log(str);
   2024                         if (cp.mApnContext != null) cp.mApnContext.requestLog(str);
   2025 
   2026                         // Transition to inactive but send notifications after
   2027                         // we've entered the mInactive state.
   2028                         mInactiveState.setEnterNotificationParams(cp,
   2029                                 DcFailCause.UNACCEPTABLE_NETWORK_PARAMETER);
   2030                         transitionTo(mInactiveState);
   2031                     } else {
   2032                         if (DBG) {
   2033                             log("DcDisconnectionErrorCreatingConnection stale EVENT_DEACTIVATE_DONE"
   2034                                     + " dp.tag=" + cp.mTag + ", mTag=" + mTag);
   2035                         }
   2036                     }
   2037                     retVal = HANDLED;
   2038                     break;
   2039 
   2040                 default:
   2041                     if (VDBG) {
   2042                         log("DcDisconnectionErrorCreatingConnection not handled msg.what="
   2043                                 + getWhatToString(msg.what));
   2044                     }
   2045                     retVal = NOT_HANDLED;
   2046                     break;
   2047             }
   2048             return retVal;
   2049         }
   2050     }
   2051     private DcDisconnectionErrorCreatingConnection mDisconnectingErrorCreatingConnection =
   2052                 new DcDisconnectionErrorCreatingConnection();
   2053 
   2054 
   2055     private class DcNetworkAgent extends NetworkAgent {
   2056         public DcNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni,
   2057                 NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
   2058             super(l, c, TAG, ni, nc, lp, score, misc);
   2059         }
   2060 
   2061         @Override
   2062         protected void unwanted() {
   2063             if (mNetworkAgent != this) {
   2064                 log("DcNetworkAgent: unwanted found mNetworkAgent=" + mNetworkAgent +
   2065                         ", which isn't me.  Aborting unwanted");
   2066                 return;
   2067             }
   2068             // this can only happen if our exit has been called - we're already disconnected
   2069             if (mApnContexts == null) return;
   2070             for (ApnContext apnContext : mApnContexts) {
   2071                 log("DcNetworkAgent: [unwanted]: disconnect apnContext=" + apnContext);
   2072                 Message msg = mDct.obtainMessage(DctConstants.EVENT_DISCONNECT_DONE, apnContext);
   2073                 DisconnectParams dp = new DisconnectParams(apnContext, apnContext.getReason(), msg);
   2074                 DataConnection.this.sendMessage(DataConnection.this.
   2075                         obtainMessage(EVENT_DISCONNECT, dp));
   2076             }
   2077         }
   2078 
   2079         @Override
   2080         protected void pollLceData() {
   2081             if(mPhone.getLceStatus() == RILConstants.LCE_ACTIVE) {  // active LCE service
   2082                 mPhone.mCi.pullLceData(DataConnection.this.obtainMessage(EVENT_BW_REFRESH_RESPONSE));
   2083             }
   2084         }
   2085     }
   2086 
   2087     // ******* "public" interface
   2088 
   2089     /**
   2090      * Used for testing purposes.
   2091      */
   2092     /* package */ void tearDownNow() {
   2093         if (DBG) log("tearDownNow()");
   2094         sendMessage(obtainMessage(EVENT_TEAR_DOWN_NOW));
   2095     }
   2096 
   2097     /**
   2098      * @return the string for msg.what as our info.
   2099      */
   2100     @Override
   2101     protected String getWhatToString(int what) {
   2102         return cmdToString(what);
   2103     }
   2104 
   2105     private static String msgToString(Message msg) {
   2106         String retVal;
   2107         if (msg == null) {
   2108             retVal = "null";
   2109         } else {
   2110             StringBuilder   b = new StringBuilder();
   2111 
   2112             b.append("{what=");
   2113             b.append(cmdToString(msg.what));
   2114 
   2115             b.append(" when=");
   2116             TimeUtils.formatDuration(msg.getWhen() - SystemClock.uptimeMillis(), b);
   2117 
   2118             if (msg.arg1 != 0) {
   2119                 b.append(" arg1=");
   2120                 b.append(msg.arg1);
   2121             }
   2122 
   2123             if (msg.arg2 != 0) {
   2124                 b.append(" arg2=");
   2125                 b.append(msg.arg2);
   2126             }
   2127 
   2128             if (msg.obj != null) {
   2129                 b.append(" obj=");
   2130                 b.append(msg.obj);
   2131             }
   2132 
   2133             b.append(" target=");
   2134             b.append(msg.getTarget());
   2135 
   2136             b.append(" replyTo=");
   2137             b.append(msg.replyTo);
   2138 
   2139             b.append("}");
   2140 
   2141             retVal = b.toString();
   2142         }
   2143         return retVal;
   2144     }
   2145 
   2146     static void slog(String s) {
   2147         Rlog.d("DC", s);
   2148     }
   2149 
   2150     /**
   2151      * Log with debug
   2152      *
   2153      * @param s is string log
   2154      */
   2155     @Override
   2156     protected void log(String s) {
   2157         Rlog.d(getName(), s);
   2158     }
   2159 
   2160     /**
   2161      * Log with debug attribute
   2162      *
   2163      * @param s is string log
   2164      */
   2165     @Override
   2166     protected void logd(String s) {
   2167         Rlog.d(getName(), s);
   2168     }
   2169 
   2170     /**
   2171      * Log with verbose attribute
   2172      *
   2173      * @param s is string log
   2174      */
   2175     @Override
   2176     protected void logv(String s) {
   2177         Rlog.v(getName(), s);
   2178     }
   2179 
   2180     /**
   2181      * Log with info attribute
   2182      *
   2183      * @param s is string log
   2184      */
   2185     @Override
   2186     protected void logi(String s) {
   2187         Rlog.i(getName(), s);
   2188     }
   2189 
   2190     /**
   2191      * Log with warning attribute
   2192      *
   2193      * @param s is string log
   2194      */
   2195     @Override
   2196     protected void logw(String s) {
   2197         Rlog.w(getName(), s);
   2198     }
   2199 
   2200     /**
   2201      * Log with error attribute
   2202      *
   2203      * @param s is string log
   2204      */
   2205     @Override
   2206     protected void loge(String s) {
   2207         Rlog.e(getName(), s);
   2208     }
   2209 
   2210     /**
   2211      * Log with error attribute
   2212      *
   2213      * @param s is string log
   2214      * @param e is a Throwable which logs additional information.
   2215      */
   2216     @Override
   2217     protected void loge(String s, Throwable e) {
   2218         Rlog.e(getName(), s, e);
   2219     }
   2220 
   2221     /** Doesn't print mApnList of ApnContext's which would be recursive */
   2222     public String toStringSimple() {
   2223         return getName() + ": State=" + getCurrentState().getName()
   2224                 + " mApnSetting=" + mApnSetting + " RefCount=" + mApnContexts.size()
   2225                 + " mCid=" + mCid + " mCreateTime=" + mCreateTime
   2226                 + " mLastastFailTime=" + mLastFailTime
   2227                 + " mLastFailCause=" + mLastFailCause
   2228                 + " mTag=" + mTag
   2229                 + " mRetryManager=" + mRetryManager
   2230                 + " mLinkProperties=" + mLinkProperties
   2231                 + " linkCapabilities=" + makeNetworkCapabilities();
   2232     }
   2233 
   2234     @Override
   2235     public String toString() {
   2236         return "{" + toStringSimple() + " mApnContexts=" + mApnContexts + "}";
   2237     }
   2238 
   2239     private void dumpToLog() {
   2240         dump(null, new PrintWriter(new StringWriter(0)) {
   2241             @Override
   2242             public void println(String s) {
   2243                 DataConnection.this.logd(s);
   2244             }
   2245 
   2246             @Override
   2247             public void flush() {
   2248             }
   2249         }, null);
   2250     }
   2251 
   2252     /**
   2253      * Dump the current state.
   2254      *
   2255      * @param fd
   2256      * @param pw
   2257      * @param args
   2258      */
   2259     @Override
   2260     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   2261         pw.print("DataConnection ");
   2262         super.dump(fd, pw, args);
   2263         pw.println(" mApnContexts.size=" + mApnContexts.size());
   2264         pw.println(" mApnContexts=" + mApnContexts);
   2265         pw.flush();
   2266         pw.println(" mDataConnectionTracker=" + mDct);
   2267         pw.println(" mApnSetting=" + mApnSetting);
   2268         pw.println(" mTag=" + mTag);
   2269         pw.println(" mCid=" + mCid);
   2270         pw.println(" mRetryManager=" + mRetryManager);
   2271         pw.println(" mConnectionParams=" + mConnectionParams);
   2272         pw.println(" mDisconnectParams=" + mDisconnectParams);
   2273         pw.println(" mDcFailCause=" + mDcFailCause);
   2274         pw.flush();
   2275         pw.println(" mPhone=" + mPhone);
   2276         pw.flush();
   2277         pw.println(" mLinkProperties=" + mLinkProperties);
   2278         pw.flush();
   2279         pw.println(" mDataRegState=" + mDataRegState);
   2280         pw.println(" mRilRat=" + mRilRat);
   2281         pw.println(" mNetworkCapabilities=" + makeNetworkCapabilities());
   2282         pw.println(" mCreateTime=" + TimeUtils.logTimeOfDay(mCreateTime));
   2283         pw.println(" mLastFailTime=" + TimeUtils.logTimeOfDay(mLastFailTime));
   2284         pw.println(" mLastFailCause=" + mLastFailCause);
   2285         pw.flush();
   2286         pw.println(" mUserData=" + mUserData);
   2287         pw.println(" mInstanceNumber=" + mInstanceNumber);
   2288         pw.println(" mAc=" + mAc);
   2289         pw.println(" mDcRetryAlarmController=" + mDcRetryAlarmController);
   2290         pw.flush();
   2291     }
   2292 }
   2293