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 static android.net.NetworkPolicyManager.OVERRIDE_CONGESTED;
     20 import static android.net.NetworkPolicyManager.OVERRIDE_UNMETERED;
     21 
     22 import android.app.PendingIntent;
     23 import android.content.Context;
     24 import android.net.ConnectivityManager;
     25 import android.net.ConnectivityManager.PacketKeepalive;
     26 import android.net.KeepalivePacketData;
     27 import android.net.LinkAddress;
     28 import android.net.LinkProperties;
     29 import android.net.NetworkAgent;
     30 import android.net.NetworkCapabilities;
     31 import android.net.NetworkInfo;
     32 import android.net.NetworkMisc;
     33 import android.net.NetworkUtils;
     34 import android.net.ProxyInfo;
     35 import android.net.RouteInfo;
     36 import android.net.StringNetworkSpecifier;
     37 import android.os.AsyncResult;
     38 import android.os.Looper;
     39 import android.os.Message;
     40 import android.os.SystemClock;
     41 import android.os.SystemProperties;
     42 import android.telephony.AccessNetworkConstants;
     43 import android.telephony.Rlog;
     44 import android.telephony.ServiceState;
     45 import android.telephony.TelephonyManager;
     46 import android.telephony.data.DataCallResponse;
     47 import android.telephony.data.DataProfile;
     48 import android.telephony.data.DataService;
     49 import android.telephony.data.DataServiceCallback;
     50 import android.text.TextUtils;
     51 import android.util.LocalLog;
     52 import android.util.Pair;
     53 import android.util.SparseArray;
     54 import android.util.StatsLog;
     55 import android.util.TimeUtils;
     56 
     57 import com.android.internal.annotations.VisibleForTesting;
     58 import com.android.internal.telephony.CallTracker;
     59 import com.android.internal.telephony.CarrierSignalAgent;
     60 import com.android.internal.telephony.DctConstants;
     61 import com.android.internal.telephony.LinkCapacityEstimate;
     62 import com.android.internal.telephony.Phone;
     63 import com.android.internal.telephony.PhoneConstants;
     64 import com.android.internal.telephony.RILConstants;
     65 import com.android.internal.telephony.RetryManager;
     66 import com.android.internal.telephony.ServiceStateTracker;
     67 import com.android.internal.telephony.TelephonyIntents;
     68 import com.android.internal.telephony.metrics.TelephonyMetrics;
     69 import com.android.internal.util.AsyncChannel;
     70 import com.android.internal.util.IndentingPrintWriter;
     71 import com.android.internal.util.Protocol;
     72 import com.android.internal.util.State;
     73 import com.android.internal.util.StateMachine;
     74 
     75 import java.io.FileDescriptor;
     76 import java.io.PrintWriter;
     77 import java.io.StringWriter;
     78 import java.net.InetAddress;
     79 import java.net.UnknownHostException;
     80 import java.util.Collection;
     81 import java.util.HashMap;
     82 import java.util.Locale;
     83 import java.util.concurrent.atomic.AtomicInteger;
     84 
     85 /**
     86  * {@hide}
     87  *
     88  * DataConnection StateMachine.
     89  *
     90  * This a class for representing a single data connection, with instances of this
     91  * class representing a connection via the cellular network. There may be multiple
     92  * data connections and all of them are managed by the <code>DataConnectionTracker</code>.
     93  *
     94  * NOTE: All DataConnection objects must be running on the same looper, which is the default
     95  * as the coordinator has members which are used without synchronization.
     96  */
     97 public class DataConnection extends StateMachine {
     98     private static final boolean DBG = true;
     99     private static final boolean VDBG = true;
    100 
    101     private static final String NETWORK_TYPE = "MOBILE";
    102 
    103     // The data connection controller
    104     private DcController mDcController;
    105 
    106     // The Tester for failing all bringup's
    107     private DcTesterFailBringUpAll mDcTesterFailBringUpAll;
    108 
    109     private static AtomicInteger mInstanceNumber = new AtomicInteger(0);
    110     private AsyncChannel mAc;
    111 
    112     // The DCT that's talking to us, we only support one!
    113     private DcTracker mDct = null;
    114 
    115     protected String[] mPcscfAddr;
    116 
    117     /**
    118      * Used internally for saving connecting parameters.
    119      */
    120     public static class ConnectionParams {
    121         int mTag;
    122         ApnContext mApnContext;
    123         int mProfileId;
    124         int mRilRat;
    125         final boolean mUnmeteredUseOnly;
    126         Message mOnCompletedMsg;
    127         final int mConnectionGeneration;
    128 
    129         ConnectionParams(ApnContext apnContext, int profileId, int rilRadioTechnology,
    130                          boolean unmeteredUseOnly,  Message onCompletedMsg,
    131                          int connectionGeneration) {
    132             mApnContext = apnContext;
    133             mProfileId = profileId;
    134             mRilRat = rilRadioTechnology;
    135             mUnmeteredUseOnly = unmeteredUseOnly;
    136             mOnCompletedMsg = onCompletedMsg;
    137             mConnectionGeneration = connectionGeneration;
    138         }
    139 
    140         @Override
    141         public String toString() {
    142             return "{mTag=" + mTag + " mApnContext=" + mApnContext
    143                     + " mProfileId=" + mProfileId
    144                     + " mRat=" + mRilRat
    145                     + " mUnmeteredUseOnly=" + mUnmeteredUseOnly
    146                     + " mOnCompletedMsg=" + msgToString(mOnCompletedMsg) + "}";
    147         }
    148     }
    149 
    150     /**
    151      * Used internally for saving disconnecting parameters.
    152      */
    153     public static class DisconnectParams {
    154         int mTag;
    155         public 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 Phone mPhone;
    179     private DataServiceManager mDataServiceManager;
    180     private LinkProperties mLinkProperties = new LinkProperties();
    181     private long mCreateTime;
    182     private long mLastFailTime;
    183     private DcFailCause mLastFailCause;
    184     private static final String NULL_IP = "0.0.0.0";
    185     private Object mUserData;
    186     private int mSubscriptionOverride;
    187     private int mRilRat = Integer.MAX_VALUE;
    188     private int mDataRegState = Integer.MAX_VALUE;
    189     private NetworkInfo mNetworkInfo;
    190     private DcNetworkAgent mNetworkAgent;
    191     private LocalLog mNetCapsLocalLog = new LocalLog(50);
    192 
    193     int mTag;
    194     public int mCid;
    195     public HashMap<ApnContext, ConnectionParams> mApnContexts = null;
    196     PendingIntent mReconnectIntent = null;
    197 
    198 
    199     // ***** Event codes for driving the state machine, package visible for Dcc
    200     static final int BASE = Protocol.BASE_DATA_CONNECTION;
    201     static final int EVENT_CONNECT = BASE + 0;
    202     static final int EVENT_SETUP_DATA_CONNECTION_DONE = BASE + 1;
    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_DATA_CONNECTION_DRS_OR_RAT_CHANGED = BASE + 11;
    211     static final int EVENT_DATA_CONNECTION_ROAM_ON = BASE + 12;
    212     static final int EVENT_DATA_CONNECTION_ROAM_OFF = BASE + 13;
    213     static final int EVENT_BW_REFRESH_RESPONSE = BASE + 14;
    214     static final int EVENT_DATA_CONNECTION_VOICE_CALL_STARTED = BASE + 15;
    215     static final int EVENT_DATA_CONNECTION_VOICE_CALL_ENDED = BASE + 16;
    216     static final int EVENT_DATA_CONNECTION_OVERRIDE_CHANGED = BASE + 17;
    217     static final int EVENT_KEEPALIVE_STATUS = BASE + 18;
    218     static final int EVENT_KEEPALIVE_STARTED = BASE + 19;
    219     static final int EVENT_KEEPALIVE_STOPPED = BASE + 20;
    220     static final int EVENT_KEEPALIVE_START_REQUEST = BASE + 21;
    221     static final int EVENT_KEEPALIVE_STOP_REQUEST = BASE + 22;
    222     static final int EVENT_LINK_CAPACITY_CHANGED = BASE + 23;
    223 
    224     private static final int CMD_TO_STRING_COUNT =
    225             EVENT_LINK_CAPACITY_CHANGED - BASE + 1;
    226 
    227     private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT];
    228     static {
    229         sCmdToString[EVENT_CONNECT - BASE] = "EVENT_CONNECT";
    230         sCmdToString[EVENT_SETUP_DATA_CONNECTION_DONE - BASE] =
    231                 "EVENT_SETUP_DATA_CONNECTION_DONE";
    232         sCmdToString[EVENT_DEACTIVATE_DONE - BASE] = "EVENT_DEACTIVATE_DONE";
    233         sCmdToString[EVENT_DISCONNECT - BASE] = "EVENT_DISCONNECT";
    234         sCmdToString[EVENT_RIL_CONNECTED - BASE] = "EVENT_RIL_CONNECTED";
    235         sCmdToString[EVENT_DISCONNECT_ALL - BASE] = "EVENT_DISCONNECT_ALL";
    236         sCmdToString[EVENT_DATA_STATE_CHANGED - BASE] = "EVENT_DATA_STATE_CHANGED";
    237         sCmdToString[EVENT_TEAR_DOWN_NOW - BASE] = "EVENT_TEAR_DOWN_NOW";
    238         sCmdToString[EVENT_LOST_CONNECTION - BASE] = "EVENT_LOST_CONNECTION";
    239         sCmdToString[EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED - BASE] =
    240                 "EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED";
    241         sCmdToString[EVENT_DATA_CONNECTION_ROAM_ON - BASE] = "EVENT_DATA_CONNECTION_ROAM_ON";
    242         sCmdToString[EVENT_DATA_CONNECTION_ROAM_OFF - BASE] = "EVENT_DATA_CONNECTION_ROAM_OFF";
    243         sCmdToString[EVENT_BW_REFRESH_RESPONSE - BASE] = "EVENT_BW_REFRESH_RESPONSE";
    244         sCmdToString[EVENT_DATA_CONNECTION_VOICE_CALL_STARTED - BASE] =
    245                 "EVENT_DATA_CONNECTION_VOICE_CALL_STARTED";
    246         sCmdToString[EVENT_DATA_CONNECTION_VOICE_CALL_ENDED - BASE] =
    247                 "EVENT_DATA_CONNECTION_VOICE_CALL_ENDED";
    248         sCmdToString[EVENT_DATA_CONNECTION_OVERRIDE_CHANGED - BASE] =
    249                 "EVENT_DATA_CONNECTION_OVERRIDE_CHANGED";
    250         sCmdToString[EVENT_KEEPALIVE_STATUS - BASE] = "EVENT_KEEPALIVE_STATUS";
    251         sCmdToString[EVENT_KEEPALIVE_STARTED - BASE] = "EVENT_KEEPALIVE_STARTED";
    252         sCmdToString[EVENT_KEEPALIVE_STOPPED - BASE] = "EVENT_KEEPALIVE_STOPPED";
    253         sCmdToString[EVENT_KEEPALIVE_START_REQUEST - BASE] = "EVENT_KEEPALIVE_START_REQUEST";
    254         sCmdToString[EVENT_KEEPALIVE_STOP_REQUEST - BASE] = "EVENT_KEEPALIVE_STOP_REQUEST";
    255         sCmdToString[EVENT_LINK_CAPACITY_CHANGED - BASE] = "EVENT_LINK_CAPACITY_CHANGED";
    256     }
    257     // Convert cmd to string or null if unknown
    258     static String cmdToString(int cmd) {
    259         String value;
    260         cmd -= BASE;
    261         if ((cmd >= 0) && (cmd < sCmdToString.length)) {
    262             value = sCmdToString[cmd];
    263         } else {
    264             value = DcAsyncChannel.cmdToString(cmd + BASE);
    265         }
    266         if (value == null) {
    267             value = "0x" + Integer.toHexString(cmd + BASE);
    268         }
    269         return value;
    270     }
    271 
    272     /**
    273      * Create the connection object
    274      *
    275      * @param phone the Phone
    276      * @param id the connection id
    277      * @return DataConnection that was created.
    278      */
    279     public static DataConnection makeDataConnection(Phone phone, int id, DcTracker dct,
    280                                                     DataServiceManager dataServiceManager,
    281                                                     DcTesterFailBringUpAll failBringUpAll,
    282                                                     DcController dcc) {
    283         DataConnection dc = new DataConnection(phone,
    284                 "DC-" + mInstanceNumber.incrementAndGet(), id, dct, dataServiceManager,
    285                 failBringUpAll, dcc);
    286         dc.start();
    287         if (DBG) dc.log("Made " + dc.getName());
    288         return dc;
    289     }
    290 
    291     void dispose() {
    292         log("dispose: call quiteNow()");
    293         quitNow();
    294     }
    295 
    296     /* Getter functions */
    297 
    298     LinkProperties getCopyLinkProperties() {
    299         return new LinkProperties(mLinkProperties);
    300     }
    301 
    302     boolean isInactive() {
    303         return getCurrentState() == mInactiveState;
    304     }
    305 
    306     boolean isDisconnecting() {
    307         return getCurrentState() == mDisconnectingState;
    308     }
    309 
    310     boolean isActive() {
    311         return getCurrentState() == mActiveState;
    312     }
    313 
    314     boolean isActivating() {
    315         return getCurrentState() == mActivatingState;
    316     }
    317 
    318     int getCid() {
    319         return mCid;
    320     }
    321 
    322     ApnSetting getApnSetting() {
    323         return mApnSetting;
    324     }
    325 
    326     void setLinkPropertiesHttpProxy(ProxyInfo proxy) {
    327         mLinkProperties.setHttpProxy(proxy);
    328     }
    329 
    330     public static class UpdateLinkPropertyResult {
    331         public SetupResult setupResult = SetupResult.SUCCESS;
    332         public LinkProperties oldLp;
    333         public LinkProperties newLp;
    334         public UpdateLinkPropertyResult(LinkProperties curLp) {
    335             oldLp = curLp;
    336             newLp = curLp;
    337         }
    338     }
    339 
    340     /**
    341      * Class returned by onSetupConnectionCompleted.
    342      */
    343     public enum SetupResult {
    344         SUCCESS,
    345         ERROR_RADIO_NOT_AVAILABLE,
    346         ERROR_INVALID_ARG,
    347         ERROR_STALE,
    348         ERROR_DATA_SERVICE_SPECIFIC_ERROR;
    349 
    350         public DcFailCause mFailCause;
    351 
    352         SetupResult() {
    353             mFailCause = DcFailCause.fromInt(0);
    354         }
    355 
    356         @Override
    357         public String toString() {
    358             return name() + "  SetupResult.mFailCause=" + mFailCause;
    359         }
    360     }
    361 
    362     public boolean isIpv4Connected() {
    363         boolean ret = false;
    364         Collection <InetAddress> addresses = mLinkProperties.getAddresses();
    365 
    366         for (InetAddress addr: addresses) {
    367             if (addr instanceof java.net.Inet4Address) {
    368                 java.net.Inet4Address i4addr = (java.net.Inet4Address) addr;
    369                 if (!i4addr.isAnyLocalAddress() && !i4addr.isLinkLocalAddress() &&
    370                         !i4addr.isLoopbackAddress() && !i4addr.isMulticastAddress()) {
    371                     ret = true;
    372                     break;
    373                 }
    374             }
    375         }
    376         return ret;
    377     }
    378 
    379     public boolean isIpv6Connected() {
    380         boolean ret = false;
    381         Collection <InetAddress> addresses = mLinkProperties.getAddresses();
    382 
    383         for (InetAddress addr: addresses) {
    384             if (addr instanceof java.net.Inet6Address) {
    385                 java.net.Inet6Address i6addr = (java.net.Inet6Address) addr;
    386                 if (!i6addr.isAnyLocalAddress() && !i6addr.isLinkLocalAddress() &&
    387                         !i6addr.isLoopbackAddress() && !i6addr.isMulticastAddress()) {
    388                     ret = true;
    389                     break;
    390                 }
    391             }
    392         }
    393         return ret;
    394     }
    395 
    396     @VisibleForTesting
    397     public UpdateLinkPropertyResult updateLinkProperty(DataCallResponse newState) {
    398         UpdateLinkPropertyResult result = new UpdateLinkPropertyResult(mLinkProperties);
    399 
    400         if (newState == null) return result;
    401 
    402         result.newLp = new LinkProperties();
    403 
    404         // set link properties based on data call response
    405         result.setupResult = setLinkProperties(newState, result.newLp);
    406         if (result.setupResult != SetupResult.SUCCESS) {
    407             if (DBG) log("updateLinkProperty failed : " + result.setupResult);
    408             return result;
    409         }
    410         // copy HTTP proxy as it is not part DataCallResponse.
    411         result.newLp.setHttpProxy(mLinkProperties.getHttpProxy());
    412 
    413         checkSetMtu(mApnSetting, result.newLp);
    414 
    415         mLinkProperties = result.newLp;
    416 
    417         updateTcpBufferSizes(mRilRat);
    418 
    419         if (DBG && (! result.oldLp.equals(result.newLp))) {
    420             log("updateLinkProperty old LP=" + result.oldLp);
    421             log("updateLinkProperty new LP=" + result.newLp);
    422         }
    423 
    424         if (result.newLp.equals(result.oldLp) == false &&
    425                 mNetworkAgent != null) {
    426             mNetworkAgent.sendLinkProperties(mLinkProperties);
    427         }
    428 
    429         return result;
    430     }
    431 
    432     /**
    433      * Read the MTU value from link properties where it can be set from network. In case
    434      * not set by the network, set it again using the mtu szie value defined in the APN
    435      * database for the connected APN
    436      */
    437     private void checkSetMtu(ApnSetting apn, LinkProperties lp) {
    438         if (lp == null) return;
    439 
    440         if (apn == null || lp == null) return;
    441 
    442         if (lp.getMtu() != PhoneConstants.UNSET_MTU) {
    443             if (DBG) log("MTU set by call response to: " + lp.getMtu());
    444             return;
    445         }
    446 
    447         if (apn != null && apn.mtu != PhoneConstants.UNSET_MTU) {
    448             lp.setMtu(apn.mtu);
    449             if (DBG) log("MTU set by APN to: " + apn.mtu);
    450             return;
    451         }
    452 
    453         int mtu = mPhone.getContext().getResources().getInteger(
    454                 com.android.internal.R.integer.config_mobile_mtu);
    455         if (mtu != PhoneConstants.UNSET_MTU) {
    456             lp.setMtu(mtu);
    457             if (DBG) log("MTU set by config resource to: " + mtu);
    458         }
    459     }
    460 
    461     //***** Constructor (NOTE: uses dcc.getHandler() as its Handler)
    462     private DataConnection(Phone phone, String name, int id,
    463                            DcTracker dct, DataServiceManager dataServiceManager,
    464                            DcTesterFailBringUpAll failBringUpAll,
    465                 DcController dcc) {
    466         super(name, dcc.getHandler());
    467         setLogRecSize(300);
    468         setLogOnlyTransitions(true);
    469         if (DBG) log("DataConnection created");
    470 
    471         mPhone = phone;
    472         mDct = dct;
    473         mDataServiceManager = dataServiceManager;
    474         mDcTesterFailBringUpAll = failBringUpAll;
    475         mDcController = dcc;
    476         mId = id;
    477         mCid = -1;
    478         ServiceState ss = mPhone.getServiceState();
    479         mRilRat = ss.getRilDataRadioTechnology();
    480         mDataRegState = mPhone.getServiceState().getDataRegState();
    481         int networkType = ss.getDataNetworkType();
    482         mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_MOBILE,
    483                 networkType, NETWORK_TYPE, TelephonyManager.getNetworkTypeName(networkType));
    484         mNetworkInfo.setRoaming(ss.getDataRoaming());
    485         mNetworkInfo.setIsAvailable(true);
    486 
    487         addState(mDefaultState);
    488             addState(mInactiveState, mDefaultState);
    489             addState(mActivatingState, mDefaultState);
    490             addState(mActiveState, mDefaultState);
    491             addState(mDisconnectingState, mDefaultState);
    492             addState(mDisconnectingErrorCreatingConnection, mDefaultState);
    493         setInitialState(mInactiveState);
    494 
    495         mApnContexts = new HashMap<>();
    496     }
    497 
    498     /**
    499      * Begin setting up a data connection, calls setupDataCall
    500      * and the ConnectionParams will be returned with the
    501      * EVENT_SETUP_DATA_CONNECTION_DONE
    502      *
    503      * @param cp is the connection parameters
    504      */
    505     private void onConnect(ConnectionParams cp) {
    506         if (DBG) log("onConnect: carrier='" + mApnSetting.carrier
    507                 + "' APN='" + mApnSetting.apn
    508                 + "' proxy='" + mApnSetting.proxy + "' port='" + mApnSetting.port + "'");
    509         if (cp.mApnContext != null) cp.mApnContext.requestLog("DataConnection.onConnect");
    510 
    511         // Check if we should fake an error.
    512         if (mDcTesterFailBringUpAll.getDcFailBringUp().mCounter  > 0) {
    513             DataCallResponse response = new DataCallResponse(
    514                     mDcTesterFailBringUpAll.getDcFailBringUp().mFailCause.getErrorCode(),
    515                     mDcTesterFailBringUpAll.getDcFailBringUp().mSuggestedRetryTime, 0, 0, "", "",
    516                     null, null, null, null, PhoneConstants.UNSET_MTU);
    517 
    518             Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
    519             AsyncResult.forMessage(msg, response, null);
    520             sendMessage(msg);
    521             if (DBG) {
    522                 log("onConnect: FailBringUpAll=" + mDcTesterFailBringUpAll.getDcFailBringUp()
    523                         + " send error response=" + response);
    524             }
    525             mDcTesterFailBringUpAll.getDcFailBringUp().mCounter -= 1;
    526             return;
    527         }
    528 
    529         mCreateTime = -1;
    530         mLastFailTime = -1;
    531         mLastFailCause = DcFailCause.NONE;
    532 
    533         Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
    534         msg.obj = cp;
    535 
    536         DataProfile dp = DcTracker.createDataProfile(mApnSetting, cp.mProfileId);
    537 
    538         // We need to use the actual modem roaming state instead of the framework roaming state
    539         // here. This flag is only passed down to ril_service for picking the correct protocol (for
    540         // old modem backward compatibility).
    541         boolean isModemRoaming = mPhone.getServiceState().getDataRoamingFromRegistration();
    542 
    543         // Set this flag to true if the user turns on data roaming. Or if we override the roaming
    544         // state in framework, we should set this flag to true as well so the modem will not reject
    545         // the data call setup (because the modem actually thinks the device is roaming).
    546         boolean allowRoaming = mPhone.getDataRoamingEnabled()
    547                 || (isModemRoaming && !mPhone.getServiceState().getDataRoaming());
    548 
    549         mDataServiceManager.setupDataCall(
    550                 ServiceState.rilRadioTechnologyToAccessNetworkType(cp.mRilRat), dp, isModemRoaming,
    551                 allowRoaming, DataService.REQUEST_REASON_NORMAL, null, msg);
    552         TelephonyMetrics.getInstance().writeSetupDataCall(mPhone.getPhoneId(), cp.mRilRat,
    553                 dp.getProfileId(), dp.getApn(), dp.getProtocol());
    554     }
    555 
    556     public void onSubscriptionOverride(int overrideMask, int overrideValue) {
    557         mSubscriptionOverride = (mSubscriptionOverride & ~overrideMask)
    558                 | (overrideValue & overrideMask);
    559         sendMessage(obtainMessage(EVENT_DATA_CONNECTION_OVERRIDE_CHANGED));
    560     }
    561 
    562     /**
    563      * TearDown the data connection when the deactivation is complete a Message with
    564      * msg.what == EVENT_DEACTIVATE_DONE
    565      *
    566      * @param o is the object returned in the AsyncResult.obj.
    567      */
    568     private void tearDownData(Object o) {
    569         int discReason = DataService.REQUEST_REASON_NORMAL;
    570         ApnContext apnContext = null;
    571         if ((o != null) && (o instanceof DisconnectParams)) {
    572             DisconnectParams dp = (DisconnectParams) o;
    573             apnContext = dp.mApnContext;
    574             if (TextUtils.equals(dp.mReason, Phone.REASON_RADIO_TURNED_OFF)
    575                     || TextUtils.equals(dp.mReason, Phone.REASON_PDP_RESET)) {
    576                 discReason = DataService.REQUEST_REASON_SHUTDOWN;
    577             }
    578         }
    579 
    580         String str = "tearDownData. mCid=" + mCid + ", reason=" + discReason;
    581         if (DBG) log(str);
    582         if (apnContext != null) apnContext.requestLog(str);
    583         mDataServiceManager.deactivateDataCall(mCid, discReason,
    584                 obtainMessage(EVENT_DEACTIVATE_DONE, mTag, 0, o));
    585     }
    586 
    587     private void notifyAllWithEvent(ApnContext alreadySent, int event, String reason) {
    588         mNetworkInfo.setDetailedState(mNetworkInfo.getDetailedState(), reason,
    589                 mNetworkInfo.getExtraInfo());
    590         for (ConnectionParams cp : mApnContexts.values()) {
    591             ApnContext apnContext = cp.mApnContext;
    592             if (apnContext == alreadySent) continue;
    593             if (reason != null) apnContext.setReason(reason);
    594             Pair<ApnContext, Integer> pair =
    595                     new Pair<ApnContext, Integer>(apnContext, cp.mConnectionGeneration);
    596             Message msg = mDct.obtainMessage(event, pair);
    597             AsyncResult.forMessage(msg);
    598             msg.sendToTarget();
    599         }
    600     }
    601 
    602     private void notifyAllOfConnected(String reason) {
    603         notifyAllWithEvent(null, DctConstants.EVENT_DATA_SETUP_COMPLETE, reason);
    604     }
    605 
    606     private void notifyAllOfDisconnectDcRetrying(String reason) {
    607         notifyAllWithEvent(null, DctConstants.EVENT_DISCONNECT_DC_RETRYING, reason);
    608     }
    609     private void notifyAllDisconnectCompleted(DcFailCause cause) {
    610         notifyAllWithEvent(null, DctConstants.EVENT_DISCONNECT_DONE, cause.toString());
    611     }
    612 
    613 
    614     /**
    615      * Send the connectionCompletedMsg.
    616      *
    617      * @param cp is the ConnectionParams
    618      * @param cause and if no error the cause is DcFailCause.NONE
    619      * @param sendAll is true if all contexts are to be notified
    620      */
    621     private void notifyConnectCompleted(ConnectionParams cp, DcFailCause cause, boolean sendAll) {
    622         ApnContext alreadySent = null;
    623 
    624         if (cp != null && cp.mOnCompletedMsg != null) {
    625             // Get the completed message but only use it once
    626             Message connectionCompletedMsg = cp.mOnCompletedMsg;
    627             cp.mOnCompletedMsg = null;
    628             alreadySent = cp.mApnContext;
    629 
    630             long timeStamp = System.currentTimeMillis();
    631             connectionCompletedMsg.arg1 = mCid;
    632 
    633             if (cause == DcFailCause.NONE) {
    634                 mCreateTime = timeStamp;
    635                 AsyncResult.forMessage(connectionCompletedMsg);
    636             } else {
    637                 mLastFailCause = cause;
    638                 mLastFailTime = timeStamp;
    639 
    640                 // Return message with a Throwable exception to signify an error.
    641                 if (cause == null) cause = DcFailCause.UNKNOWN;
    642                 AsyncResult.forMessage(connectionCompletedMsg, cause,
    643                         new Throwable(cause.toString()));
    644             }
    645             if (DBG) {
    646                 log("notifyConnectCompleted at " + timeStamp + " cause=" + cause
    647                         + " connectionCompletedMsg=" + msgToString(connectionCompletedMsg));
    648             }
    649 
    650             connectionCompletedMsg.sendToTarget();
    651         }
    652         if (sendAll) {
    653             log("Send to all. " + alreadySent + " " + cause.toString());
    654             notifyAllWithEvent(alreadySent, DctConstants.EVENT_DATA_SETUP_COMPLETE_ERROR,
    655                     cause.toString());
    656         }
    657     }
    658 
    659     /**
    660      * Send ar.userObj if its a message, which is should be back to originator.
    661      *
    662      * @param dp is the DisconnectParams.
    663      */
    664     private void notifyDisconnectCompleted(DisconnectParams dp, boolean sendAll) {
    665         if (VDBG) log("NotifyDisconnectCompleted");
    666 
    667         ApnContext alreadySent = null;
    668         String reason = null;
    669 
    670         if (dp != null && dp.mOnCompletedMsg != null) {
    671             // Get the completed message but only use it once
    672             Message msg = dp.mOnCompletedMsg;
    673             dp.mOnCompletedMsg = null;
    674             if (msg.obj instanceof ApnContext) {
    675                 alreadySent = (ApnContext)msg.obj;
    676             }
    677             reason = dp.mReason;
    678             if (VDBG) {
    679                 log(String.format("msg=%s msg.obj=%s", msg.toString(),
    680                     ((msg.obj instanceof String) ? (String) msg.obj : "<no-reason>")));
    681             }
    682             AsyncResult.forMessage(msg);
    683             msg.sendToTarget();
    684         }
    685         if (sendAll) {
    686             if (reason == null) {
    687                 reason = DcFailCause.UNKNOWN.toString();
    688             }
    689             notifyAllWithEvent(alreadySent, DctConstants.EVENT_DISCONNECT_DONE, reason);
    690         }
    691         if (DBG) log("NotifyDisconnectCompleted DisconnectParams=" + dp);
    692     }
    693 
    694     /*
    695      * **************************************************************************
    696      * Begin Members and methods owned by DataConnectionTracker but stored
    697      * in a DataConnection because there is one per connection.
    698      * **************************************************************************
    699      */
    700 
    701     /*
    702      * The id is owned by DataConnectionTracker.
    703      */
    704     private int mId;
    705 
    706     /**
    707      * Get the DataConnection ID
    708      */
    709     public int getDataConnectionId() {
    710         return mId;
    711     }
    712 
    713     /*
    714      * **************************************************************************
    715      * End members owned by DataConnectionTracker
    716      * **************************************************************************
    717      */
    718 
    719     /**
    720      * Clear all settings called when entering mInactiveState.
    721      */
    722     private void clearSettings() {
    723         if (DBG) log("clearSettings");
    724 
    725         mCreateTime = -1;
    726         mLastFailTime = -1;
    727         mLastFailCause = DcFailCause.NONE;
    728         mCid = -1;
    729 
    730         mPcscfAddr = new String[5];
    731 
    732         mLinkProperties = new LinkProperties();
    733         mApnContexts.clear();
    734         mApnSetting = null;
    735         mDcFailCause = null;
    736     }
    737 
    738     /**
    739      * Process setup data completion result from data service
    740      *
    741      * @param resultCode The result code returned by data service
    742      * @param response Data call setup response from data service
    743      * @param cp The original connection params used for data call setup
    744      * @return Setup result
    745      */
    746     private SetupResult onSetupConnectionCompleted(@DataServiceCallback.ResultCode int resultCode,
    747                                                    DataCallResponse response,
    748                                                    ConnectionParams cp) {
    749         SetupResult result;
    750 
    751         if (cp.mTag != mTag) {
    752             if (DBG) {
    753                 log("onSetupConnectionCompleted stale cp.tag=" + cp.mTag + ", mtag=" + mTag);
    754             }
    755             result = SetupResult.ERROR_STALE;
    756         } else if (resultCode == DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE) {
    757             result = SetupResult.ERROR_RADIO_NOT_AVAILABLE;
    758             result.mFailCause = DcFailCause.RADIO_NOT_AVAILABLE;
    759         } else if (response.getStatus() != 0) {
    760             if (response.getStatus() == DcFailCause.RADIO_NOT_AVAILABLE.getErrorCode()) {
    761                 result = SetupResult.ERROR_RADIO_NOT_AVAILABLE;
    762                 result.mFailCause = DcFailCause.RADIO_NOT_AVAILABLE;
    763             } else {
    764                 result = SetupResult.ERROR_DATA_SERVICE_SPECIFIC_ERROR;
    765                 result.mFailCause = DcFailCause.fromInt(response.getStatus());
    766             }
    767         } else {
    768             if (DBG) log("onSetupConnectionCompleted received successful DataCallResponse");
    769             mCid = response.getCallId();
    770 
    771             mPcscfAddr = response.getPcscfs().toArray(new String[response.getPcscfs().size()]);
    772 
    773             result = updateLinkProperty(response).setupResult;
    774         }
    775 
    776         return result;
    777     }
    778 
    779     private boolean isDnsOk(String[] domainNameServers) {
    780         if (NULL_IP.equals(domainNameServers[0]) && NULL_IP.equals(domainNameServers[1])
    781                 && !mPhone.isDnsCheckDisabled()) {
    782             // Work around a race condition where QMI does not fill in DNS:
    783             // Deactivate PDP and let DataConnectionTracker retry.
    784             // Do not apply the race condition workaround for MMS APN
    785             // if Proxy is an IP-address.
    786             // Otherwise, the default APN will not be restored anymore.
    787             if (!mApnSetting.types[0].equals(PhoneConstants.APN_TYPE_MMS)
    788                 || !isIpAddress(mApnSetting.mmsProxy)) {
    789                 log(String.format(
    790                         "isDnsOk: return false apn.types[0]=%s APN_TYPE_MMS=%s isIpAddress(%s)=%s",
    791                         mApnSetting.types[0], PhoneConstants.APN_TYPE_MMS, mApnSetting.mmsProxy,
    792                         isIpAddress(mApnSetting.mmsProxy)));
    793                 return false;
    794             }
    795         }
    796         return true;
    797     }
    798 
    799     private static final String TCP_BUFFER_SIZES_GPRS = "4092,8760,48000,4096,8760,48000";
    800     private static final String TCP_BUFFER_SIZES_EDGE = "4093,26280,70800,4096,16384,70800";
    801     private static final String TCP_BUFFER_SIZES_UMTS = "58254,349525,1048576,58254,349525,1048576";
    802     private static final String TCP_BUFFER_SIZES_1XRTT= "16384,32768,131072,4096,16384,102400";
    803     private static final String TCP_BUFFER_SIZES_EVDO = "4094,87380,262144,4096,16384,262144";
    804     private static final String TCP_BUFFER_SIZES_EHRPD= "131072,262144,1048576,4096,16384,524288";
    805     private static final String TCP_BUFFER_SIZES_HSDPA= "61167,367002,1101005,8738,52429,262114";
    806     private static final String TCP_BUFFER_SIZES_HSPA = "40778,244668,734003,16777,100663,301990";
    807     private static final String TCP_BUFFER_SIZES_LTE  =
    808             "524288,1048576,2097152,262144,524288,1048576";
    809     private static final String TCP_BUFFER_SIZES_HSPAP= "122334,734003,2202010,32040,192239,576717";
    810 
    811     private void updateTcpBufferSizes(int rilRat) {
    812         String sizes = null;
    813         if (rilRat == ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA) {
    814             // for now treat CA as LTE.  Plan to surface the extra bandwith in a more
    815             // precise manner which should affect buffer sizes
    816             rilRat = ServiceState.RIL_RADIO_TECHNOLOGY_LTE;
    817         }
    818         String ratName = ServiceState.rilRadioTechnologyToString(rilRat).toLowerCase(Locale.ROOT);
    819         // ServiceState gives slightly different names for EVDO tech ("evdo-rev.0" for ex)
    820         // - patch it up:
    821         if (rilRat == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0 ||
    822                 rilRat == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A ||
    823                 rilRat == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B) {
    824             ratName = "evdo";
    825         }
    826 
    827         // in the form: "ratname:rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max"
    828         String[] configOverride = mPhone.getContext().getResources().getStringArray(
    829                 com.android.internal.R.array.config_mobile_tcp_buffers);
    830         for (int i = 0; i < configOverride.length; i++) {
    831             String[] split = configOverride[i].split(":");
    832             if (ratName.equals(split[0]) && split.length == 2) {
    833                 sizes = split[1];
    834                 break;
    835             }
    836         }
    837 
    838         if (sizes == null) {
    839             // no override - use telephony defaults
    840             // doing it this way allows device or carrier to just override the types they
    841             // care about and inherit the defaults for the others.
    842             switch (rilRat) {
    843                 case ServiceState.RIL_RADIO_TECHNOLOGY_GPRS:
    844                     sizes = TCP_BUFFER_SIZES_GPRS;
    845                     break;
    846                 case ServiceState.RIL_RADIO_TECHNOLOGY_EDGE:
    847                     sizes = TCP_BUFFER_SIZES_EDGE;
    848                     break;
    849                 case ServiceState.RIL_RADIO_TECHNOLOGY_UMTS:
    850                     sizes = TCP_BUFFER_SIZES_UMTS;
    851                     break;
    852                 case ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT:
    853                     sizes = TCP_BUFFER_SIZES_1XRTT;
    854                     break;
    855                 case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0:
    856                 case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A:
    857                 case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B:
    858                     sizes = TCP_BUFFER_SIZES_EVDO;
    859                     break;
    860                 case ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD:
    861                     sizes = TCP_BUFFER_SIZES_EHRPD;
    862                     break;
    863                 case ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA:
    864                     sizes = TCP_BUFFER_SIZES_HSDPA;
    865                     break;
    866                 case ServiceState.RIL_RADIO_TECHNOLOGY_HSPA:
    867                 case ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA:
    868                     sizes = TCP_BUFFER_SIZES_HSPA;
    869                     break;
    870                 case ServiceState.RIL_RADIO_TECHNOLOGY_LTE:
    871                 case ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA:
    872                     sizes = TCP_BUFFER_SIZES_LTE;
    873                     break;
    874                 case ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP:
    875                     sizes = TCP_BUFFER_SIZES_HSPAP;
    876                     break;
    877                 default:
    878                     // Leave empty - this will let ConnectivityService use the system default.
    879                     break;
    880             }
    881         }
    882         mLinkProperties.setTcpBufferSizes(sizes);
    883     }
    884 
    885     /**
    886      * Indicates if when this connection was established we had a restricted/privileged
    887      * NetworkRequest and needed it to overcome data-enabled limitations.
    888      *
    889      * This gets set once per connection setup and is based on conditions at that time.
    890      * We could theoretically have dynamic capabilities but now is not a good time to
    891      * experiment with that.
    892      *
    893      * This flag overrides the APN-based restriction capability, restricting the network
    894      * based on both having a NetworkRequest with restricted AND needing a restricted
    895      * bit to overcome user-disabled status.  This allows us to handle the common case
    896      * of having both restricted requests and unrestricted requests for the same apn:
    897      * if conditions require a restricted network to overcome user-disabled then it must
    898      * be restricted, otherwise it is unrestricted (or restricted based on APN type).
    899      *
    900      * Because we're not supporting dynamic capabilities, if conditions change and we go from
    901      * data-enabled to not or vice-versa we will need to tear down networks to deal with it
    902      * at connection setup time with the new state.
    903      *
    904      * This supports a privileged app bringing up a network without general apps having access
    905      * to it when the network is otherwise unavailable (hipri).  The first use case is
    906      * pre-paid SIM reprovisioning over internet, where the carrier insists on no traffic
    907      * other than from the privileged carrier-app.
    908      */
    909     private boolean mRestrictedNetworkOverride = false;
    910 
    911     // Should be called once when the call goes active to examine the state of things and
    912     // declare the restriction override for the life of the connection
    913     private void setNetworkRestriction() {
    914         mRestrictedNetworkOverride = false;
    915         // first, if we have no restricted requests, this override can stay FALSE:
    916         boolean noRestrictedRequests = true;
    917         for (ApnContext apnContext : mApnContexts.keySet()) {
    918             noRestrictedRequests &= apnContext.hasNoRestrictedRequests(true /* exclude DUN */);
    919         }
    920         if (noRestrictedRequests) {
    921             return;
    922         }
    923 
    924         // Do we need a restricted network to satisfy the request?
    925         // Is this network metered?  If not, then don't add restricted
    926         if (!mApnSetting.isMetered(mPhone)) {
    927             return;
    928         }
    929 
    930         // Is data disabled?
    931         mRestrictedNetworkOverride = !mDct.isDataEnabled();
    932     }
    933 
    934     NetworkCapabilities getNetworkCapabilities() {
    935         NetworkCapabilities result = new NetworkCapabilities();
    936         result.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
    937 
    938         if (mApnSetting != null) {
    939             for (String type : mApnSetting.types) {
    940                 if (!mRestrictedNetworkOverride
    941                         && (mConnectionParams != null && mConnectionParams.mUnmeteredUseOnly)
    942                         && ApnSetting.isMeteredApnType(type, mPhone)) {
    943                     log("Dropped the metered " + type + " for the unmetered data call.");
    944                     continue;
    945                 }
    946                 switch (type) {
    947                     case PhoneConstants.APN_TYPE_ALL: {
    948                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
    949                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
    950                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
    951                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA);
    952                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
    953                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_CBS);
    954                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_IA);
    955                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
    956                         break;
    957                     }
    958                     case PhoneConstants.APN_TYPE_DEFAULT: {
    959                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
    960                         break;
    961                     }
    962                     case PhoneConstants.APN_TYPE_MMS: {
    963                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
    964                         break;
    965                     }
    966                     case PhoneConstants.APN_TYPE_SUPL: {
    967                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
    968                         break;
    969                     }
    970                     case PhoneConstants.APN_TYPE_DUN: {
    971                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
    972                         break;
    973                     }
    974                     case PhoneConstants.APN_TYPE_FOTA: {
    975                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA);
    976                         break;
    977                     }
    978                     case PhoneConstants.APN_TYPE_IMS: {
    979                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
    980                         break;
    981                     }
    982                     case PhoneConstants.APN_TYPE_CBS: {
    983                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_CBS);
    984                         break;
    985                     }
    986                     case PhoneConstants.APN_TYPE_IA: {
    987                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_IA);
    988                         break;
    989                     }
    990                     case PhoneConstants.APN_TYPE_EMERGENCY: {
    991                         result.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS);
    992                         break;
    993                     }
    994                     default:
    995                 }
    996             }
    997 
    998             // Mark NOT_METERED in the following cases,
    999             // 1. All APNs in APN settings are unmetered.
   1000             // 2. The non-restricted data and is intended for unmetered use only.
   1001             if (((mConnectionParams != null && mConnectionParams.mUnmeteredUseOnly)
   1002                     && !mRestrictedNetworkOverride)
   1003                     || !mApnSetting.isMetered(mPhone)) {
   1004                 result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
   1005             } else {
   1006                 result.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
   1007             }
   1008 
   1009             result.maybeMarkCapabilitiesRestricted();
   1010         }
   1011         if (mRestrictedNetworkOverride) {
   1012             result.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
   1013             // don't use dun on restriction-overriden networks.
   1014             result.removeCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
   1015         }
   1016 
   1017         int up = 14;
   1018         int down = 14;
   1019         switch (mRilRat) {
   1020             case ServiceState.RIL_RADIO_TECHNOLOGY_GPRS: up = 80; down = 80; break;
   1021             case ServiceState.RIL_RADIO_TECHNOLOGY_EDGE: up = 59; down = 236; break;
   1022             case ServiceState.RIL_RADIO_TECHNOLOGY_UMTS: up = 384; down = 384; break;
   1023             case ServiceState.RIL_RADIO_TECHNOLOGY_IS95A: // fall through
   1024             case ServiceState.RIL_RADIO_TECHNOLOGY_IS95B: up = 14; down = 14; break;
   1025             case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0: up = 153; down = 2457; break;
   1026             case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A: up = 1843; down = 3174; break;
   1027             case ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT: up = 100; down = 100; break;
   1028             case ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA: up = 2048; down = 14336; break;
   1029             case ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA: up = 5898; down = 14336; break;
   1030             case ServiceState.RIL_RADIO_TECHNOLOGY_HSPA: up = 5898; down = 14336; break;
   1031             case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B: up = 1843; down = 5017; break;
   1032             case ServiceState.RIL_RADIO_TECHNOLOGY_LTE: up = 51200; down = 102400; break;
   1033             case ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA: up = 51200; down = 102400; break;
   1034             case ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD: up = 153; down = 2516; break;
   1035             case ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP: up = 11264; down = 43008; break;
   1036             default:
   1037         }
   1038         result.setLinkUpstreamBandwidthKbps(up);
   1039         result.setLinkDownstreamBandwidthKbps(down);
   1040 
   1041         result.setNetworkSpecifier(new StringNetworkSpecifier(Integer.toString(mPhone.getSubId())));
   1042 
   1043         result.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING,
   1044                 !mPhone.getServiceState().getDataRoaming());
   1045 
   1046         result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
   1047 
   1048         // Override values set above when requested by policy
   1049         if ((mSubscriptionOverride & OVERRIDE_UNMETERED) != 0) {
   1050             result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
   1051         }
   1052         if ((mSubscriptionOverride & OVERRIDE_CONGESTED) != 0) {
   1053             result.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
   1054         }
   1055 
   1056         return result;
   1057     }
   1058 
   1059     /**
   1060      * @return {@code} true iff. {@code address} is a literal IPv4 or IPv6 address.
   1061      */
   1062     @VisibleForTesting
   1063     public static boolean isIpAddress(String address) {
   1064         if (address == null) return false;
   1065 
   1066         return InetAddress.isNumeric(address);
   1067     }
   1068 
   1069     private SetupResult setLinkProperties(DataCallResponse response,
   1070             LinkProperties linkProperties) {
   1071         // Check if system property dns usable
   1072         String propertyPrefix = "net." + response.getIfname() + ".";
   1073         String dnsServers[] = new String[2];
   1074         dnsServers[0] = SystemProperties.get(propertyPrefix + "dns1");
   1075         dnsServers[1] = SystemProperties.get(propertyPrefix + "dns2");
   1076         boolean okToUseSystemPropertyDns = isDnsOk(dnsServers);
   1077 
   1078         SetupResult result;
   1079 
   1080         // Start with clean network properties and if we have
   1081         // a failure we'll clear again at the bottom of this code.
   1082         linkProperties.clear();
   1083 
   1084         if (response.getStatus() == DcFailCause.NONE.getErrorCode()) {
   1085             try {
   1086                 // set interface name
   1087                 linkProperties.setInterfaceName(response.getIfname());
   1088 
   1089                 // set link addresses
   1090                 if (response.getAddresses().size() > 0) {
   1091                     for (LinkAddress la : response.getAddresses()) {
   1092                         if (!la.getAddress().isAnyLocalAddress()) {
   1093                             if (DBG) {
   1094                                 log("addr/pl=" + la.getAddress() + "/"
   1095                                         + la.getNetworkPrefixLength());
   1096                             }
   1097                             linkProperties.addLinkAddress(la);
   1098                         }
   1099                     }
   1100                 } else {
   1101                     throw new UnknownHostException("no address for ifname=" + response.getIfname());
   1102                 }
   1103 
   1104                 // set dns servers
   1105                 if (response.getDnses().size() > 0) {
   1106                     for (InetAddress dns : response.getDnses()) {
   1107                         if (!dns.isAnyLocalAddress()) {
   1108                             linkProperties.addDnsServer(dns);
   1109                         }
   1110                     }
   1111                 } else if (okToUseSystemPropertyDns) {
   1112                     for (String dnsAddr : dnsServers) {
   1113                         dnsAddr = dnsAddr.trim();
   1114                         if (dnsAddr.isEmpty()) continue;
   1115                         InetAddress ia;
   1116                         try {
   1117                             ia = NetworkUtils.numericToInetAddress(dnsAddr);
   1118                         } catch (IllegalArgumentException e) {
   1119                             throw new UnknownHostException("Non-numeric dns addr=" + dnsAddr);
   1120                         }
   1121                         if (!ia.isAnyLocalAddress()) {
   1122                             linkProperties.addDnsServer(ia);
   1123                         }
   1124                     }
   1125                 } else {
   1126                     throw new UnknownHostException("Empty dns response and no system default dns");
   1127                 }
   1128 
   1129                 for (InetAddress gateway : response.getGateways()) {
   1130                     // Allow 0.0.0.0 or :: as a gateway;
   1131                     // this indicates a point-to-point interface.
   1132                     linkProperties.addRoute(new RouteInfo(gateway));
   1133                 }
   1134 
   1135                 // set interface MTU
   1136                 // this may clobber the setting read from the APN db, but that's ok
   1137                 linkProperties.setMtu(response.getMtu());
   1138 
   1139                 result = SetupResult.SUCCESS;
   1140             } catch (UnknownHostException e) {
   1141                 log("setLinkProperties: UnknownHostException " + e);
   1142                 result = SetupResult.ERROR_INVALID_ARG;
   1143             }
   1144         } else {
   1145             result = SetupResult.ERROR_DATA_SERVICE_SPECIFIC_ERROR;
   1146         }
   1147 
   1148         // An error occurred so clear properties
   1149         if (result != SetupResult.SUCCESS) {
   1150             if (DBG) {
   1151                 log("setLinkProperties: error clearing LinkProperties status="
   1152                         + response.getStatus() + " result=" + result);
   1153             }
   1154             linkProperties.clear();
   1155         }
   1156 
   1157         return result;
   1158     }
   1159 
   1160     /**
   1161      * Initialize connection, this will fail if the
   1162      * apnSettings are not compatible.
   1163      *
   1164      * @param cp the Connection parameters
   1165      * @return true if initialization was successful.
   1166      */
   1167     private boolean initConnection(ConnectionParams cp) {
   1168         ApnContext apnContext = cp.mApnContext;
   1169         if (mApnSetting == null) {
   1170             // Only change apn setting if it isn't set, it will
   1171             // only NOT be set only if we're in DcInactiveState.
   1172             mApnSetting = apnContext.getApnSetting();
   1173         }
   1174         if (mApnSetting == null || !mApnSetting.canHandleType(apnContext.getApnType())) {
   1175             if (DBG) {
   1176                 log("initConnection: incompatible apnSetting in ConnectionParams cp=" + cp
   1177                         + " dc=" + DataConnection.this);
   1178             }
   1179             return false;
   1180         }
   1181         mTag += 1;
   1182         mConnectionParams = cp;
   1183         mConnectionParams.mTag = mTag;
   1184 
   1185         // always update the ConnectionParams with the latest or the
   1186         // connectionGeneration gets stale
   1187         mApnContexts.put(apnContext, cp);
   1188 
   1189         if (DBG) {
   1190             log("initConnection: "
   1191                     + " RefCount=" + mApnContexts.size()
   1192                     + " mApnList=" + mApnContexts
   1193                     + " mConnectionParams=" + mConnectionParams);
   1194         }
   1195         return true;
   1196     }
   1197 
   1198     /**
   1199      * The parent state for all other states.
   1200      */
   1201     private class DcDefaultState extends State {
   1202         @Override
   1203         public void enter() {
   1204             if (DBG) log("DcDefaultState: enter");
   1205 
   1206             // Register for DRS or RAT change
   1207             mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(getHandler(),
   1208                     DataConnection.EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED, null);
   1209 
   1210             mPhone.getServiceStateTracker().registerForDataRoamingOn(getHandler(),
   1211                     DataConnection.EVENT_DATA_CONNECTION_ROAM_ON, null);
   1212             mPhone.getServiceStateTracker().registerForDataRoamingOff(getHandler(),
   1213                     DataConnection.EVENT_DATA_CONNECTION_ROAM_OFF, null, true);
   1214 
   1215             // Add ourselves to the list of data connections
   1216             mDcController.addDc(DataConnection.this);
   1217         }
   1218         @Override
   1219         public void exit() {
   1220             if (DBG) log("DcDefaultState: exit");
   1221 
   1222             // Unregister for DRS or RAT change.
   1223             mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(getHandler());
   1224 
   1225             mPhone.getServiceStateTracker().unregisterForDataRoamingOn(getHandler());
   1226             mPhone.getServiceStateTracker().unregisterForDataRoamingOff(getHandler());
   1227 
   1228             // Remove ourselves from the DC lists
   1229             mDcController.removeDc(DataConnection.this);
   1230 
   1231             if (mAc != null) {
   1232                 mAc.disconnected();
   1233                 mAc = null;
   1234             }
   1235             mApnContexts = null;
   1236             mReconnectIntent = null;
   1237             mDct = null;
   1238             mApnSetting = null;
   1239             mPhone = null;
   1240             mDataServiceManager = null;
   1241             mLinkProperties = null;
   1242             mLastFailCause = null;
   1243             mUserData = null;
   1244             mDcController = null;
   1245             mDcTesterFailBringUpAll = null;
   1246         }
   1247 
   1248         @Override
   1249         public boolean processMessage(Message msg) {
   1250             boolean retVal = HANDLED;
   1251 
   1252             if (VDBG) {
   1253                 log("DcDefault msg=" + getWhatToString(msg.what)
   1254                         + " RefCount=" + mApnContexts.size());
   1255             }
   1256             switch (msg.what) {
   1257                 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
   1258                     if (mAc != null) {
   1259                         if (VDBG) log("Disconnecting to previous connection mAc=" + mAc);
   1260                         mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
   1261                                 AsyncChannel.STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED);
   1262                     } else {
   1263                         mAc = new AsyncChannel();
   1264                         mAc.connected(null, getHandler(), msg.replyTo);
   1265                         if (VDBG) log("DcDefaultState: FULL_CONNECTION reply connected");
   1266                         mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
   1267                                 AsyncChannel.STATUS_SUCCESSFUL, mId, "hi");
   1268                     }
   1269                     break;
   1270                 }
   1271                 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
   1272                     if (DBG) {
   1273                         log("DcDefault: CMD_CHANNEL_DISCONNECTED before quiting call dump");
   1274                         dumpToLog();
   1275                     }
   1276 
   1277                     quit();
   1278                     break;
   1279                 }
   1280                 case DcAsyncChannel.REQ_IS_INACTIVE: {
   1281                     boolean val = isInactive();
   1282                     if (VDBG) log("REQ_IS_INACTIVE  isInactive=" + val);
   1283                     mAc.replyToMessage(msg, DcAsyncChannel.RSP_IS_INACTIVE, val ? 1 : 0);
   1284                     break;
   1285                 }
   1286                 case DcAsyncChannel.REQ_GET_CID: {
   1287                     int cid = getCid();
   1288                     if (VDBG) log("REQ_GET_CID  cid=" + cid);
   1289                     mAc.replyToMessage(msg, DcAsyncChannel.RSP_GET_CID, cid);
   1290                     break;
   1291                 }
   1292                 case DcAsyncChannel.REQ_GET_APNSETTING: {
   1293                     ApnSetting apnSetting = getApnSetting();
   1294                     if (VDBG) log("REQ_GET_APNSETTING  mApnSetting=" + apnSetting);
   1295                     mAc.replyToMessage(msg, DcAsyncChannel.RSP_GET_APNSETTING, apnSetting);
   1296                     break;
   1297                 }
   1298                 case DcAsyncChannel.REQ_GET_LINK_PROPERTIES: {
   1299                     LinkProperties lp = getCopyLinkProperties();
   1300                     if (VDBG) log("REQ_GET_LINK_PROPERTIES linkProperties" + lp);
   1301                     mAc.replyToMessage(msg, DcAsyncChannel.RSP_GET_LINK_PROPERTIES, lp);
   1302                     break;
   1303                 }
   1304                 case DcAsyncChannel.REQ_SET_LINK_PROPERTIES_HTTP_PROXY: {
   1305                     ProxyInfo proxy = (ProxyInfo) msg.obj;
   1306                     if (VDBG) log("REQ_SET_LINK_PROPERTIES_HTTP_PROXY proxy=" + proxy);
   1307                     setLinkPropertiesHttpProxy(proxy);
   1308                     mAc.replyToMessage(msg, DcAsyncChannel.RSP_SET_LINK_PROPERTIES_HTTP_PROXY);
   1309                     if (mNetworkAgent != null) {
   1310                         mNetworkAgent.sendLinkProperties(mLinkProperties);
   1311                     }
   1312                     break;
   1313                 }
   1314                 case DcAsyncChannel.REQ_GET_NETWORK_CAPABILITIES: {
   1315                     NetworkCapabilities nc = getNetworkCapabilities();
   1316                     if (VDBG) log("REQ_GET_NETWORK_CAPABILITIES networkCapabilities" + nc);
   1317                     mAc.replyToMessage(msg, DcAsyncChannel.RSP_GET_NETWORK_CAPABILITIES, nc);
   1318                     break;
   1319                 }
   1320                 case DcAsyncChannel.REQ_RESET:
   1321                     if (VDBG) log("DcDefaultState: msg.what=REQ_RESET");
   1322                     transitionTo(mInactiveState);
   1323                     break;
   1324                 case EVENT_CONNECT:
   1325                     if (DBG) log("DcDefaultState: msg.what=EVENT_CONNECT, fail not expected");
   1326                     ConnectionParams cp = (ConnectionParams) msg.obj;
   1327                     notifyConnectCompleted(cp, DcFailCause.UNKNOWN, false);
   1328                     break;
   1329 
   1330                 case EVENT_DISCONNECT:
   1331                     if (DBG) {
   1332                         log("DcDefaultState deferring msg.what=EVENT_DISCONNECT RefCount="
   1333                                 + mApnContexts.size());
   1334                     }
   1335                     deferMessage(msg);
   1336                     break;
   1337 
   1338                 case EVENT_DISCONNECT_ALL:
   1339                     if (DBG) {
   1340                         log("DcDefaultState deferring msg.what=EVENT_DISCONNECT_ALL RefCount="
   1341                                 + mApnContexts.size());
   1342                     }
   1343                     deferMessage(msg);
   1344                     break;
   1345                 case EVENT_TEAR_DOWN_NOW:
   1346                     if (DBG) log("DcDefaultState EVENT_TEAR_DOWN_NOW");
   1347                     mDataServiceManager.deactivateDataCall(mCid, DataService.REQUEST_REASON_NORMAL,
   1348                             null);
   1349                     break;
   1350                 case EVENT_LOST_CONNECTION:
   1351                     if (DBG) {
   1352                         String s = "DcDefaultState ignore EVENT_LOST_CONNECTION"
   1353                                 + " tag=" + msg.arg1 + ":mTag=" + mTag;
   1354                         logAndAddLogRec(s);
   1355                     }
   1356                     break;
   1357                 case EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED:
   1358                     AsyncResult ar = (AsyncResult)msg.obj;
   1359                     Pair<Integer, Integer> drsRatPair = (Pair<Integer, Integer>)ar.result;
   1360                     mDataRegState = drsRatPair.first;
   1361                     if (mRilRat != drsRatPair.second) {
   1362                         updateTcpBufferSizes(drsRatPair.second);
   1363                     }
   1364                     mRilRat = drsRatPair.second;
   1365                     if (DBG) {
   1366                         log("DcDefaultState: EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED"
   1367                                 + " drs=" + mDataRegState
   1368                                 + " mRilRat=" + mRilRat);
   1369                     }
   1370                     updateNetworkInfo();
   1371                     updateNetworkInfoSuspendState();
   1372                     if (mNetworkAgent != null) {
   1373                         mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities());
   1374                         mNetworkAgent.sendNetworkInfo(mNetworkInfo);
   1375                         mNetworkAgent.sendLinkProperties(mLinkProperties);
   1376                     }
   1377                     break;
   1378                 case EVENT_DATA_CONNECTION_ROAM_ON:
   1379                 case EVENT_DATA_CONNECTION_ROAM_OFF:
   1380                 case EVENT_DATA_CONNECTION_OVERRIDE_CHANGED:
   1381                     updateNetworkInfo();
   1382                     if (mNetworkAgent != null) {
   1383                         mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities());
   1384                         mNetworkAgent.sendNetworkInfo(mNetworkInfo);
   1385                     }
   1386                     break;
   1387                 case EVENT_KEEPALIVE_START_REQUEST:
   1388                 case EVENT_KEEPALIVE_STOP_REQUEST:
   1389                     if (mNetworkAgent != null) {
   1390                         mNetworkAgent.onPacketKeepaliveEvent(
   1391                                 msg.arg1,
   1392                                 ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
   1393                     }
   1394                     break;
   1395                 default:
   1396                     if (DBG) {
   1397                         log("DcDefaultState: shouldn't happen but ignore msg.what="
   1398                                 + getWhatToString(msg.what));
   1399                     }
   1400                     break;
   1401             }
   1402 
   1403             return retVal;
   1404         }
   1405     }
   1406 
   1407     private void updateNetworkInfo() {
   1408         final ServiceState state = mPhone.getServiceState();
   1409         final int subtype = state.getDataNetworkType();
   1410         mNetworkInfo.setSubtype(subtype, TelephonyManager.getNetworkTypeName(subtype));
   1411         mNetworkInfo.setRoaming(state.getDataRoaming());
   1412     }
   1413 
   1414     private void updateNetworkInfoSuspendState() {
   1415         // this is only called when we are either connected or suspended.  Decide which.
   1416         if (mNetworkAgent == null) {
   1417             Rlog.e(getName(), "Setting suspend state without a NetworkAgent");
   1418         }
   1419 
   1420         // if we are not in-service change to SUSPENDED
   1421         final ServiceStateTracker sst = mPhone.getServiceStateTracker();
   1422         if (sst.getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
   1423             mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, null,
   1424                     mNetworkInfo.getExtraInfo());
   1425         } else {
   1426             // check for voice call and concurrency issues
   1427             if (sst.isConcurrentVoiceAndDataAllowed() == false) {
   1428                 final CallTracker ct = mPhone.getCallTracker();
   1429                 if (ct.getState() != PhoneConstants.State.IDLE) {
   1430                     mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, null,
   1431                             mNetworkInfo.getExtraInfo());
   1432                     return;
   1433                 }
   1434             }
   1435             mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null,
   1436                     mNetworkInfo.getExtraInfo());
   1437         }
   1438     }
   1439 
   1440     private DcDefaultState mDefaultState = new DcDefaultState();
   1441 
   1442     /**
   1443      * The state machine is inactive and expects a EVENT_CONNECT.
   1444      */
   1445     private class DcInactiveState extends State {
   1446         // Inform all contexts we've failed connecting
   1447         public void setEnterNotificationParams(ConnectionParams cp, DcFailCause cause) {
   1448             if (VDBG) log("DcInactiveState: setEnterNotificationParams cp,cause");
   1449             mConnectionParams = cp;
   1450             mDisconnectParams = null;
   1451             mDcFailCause = cause;
   1452         }
   1453 
   1454         // Inform all contexts we've failed disconnected
   1455         public void setEnterNotificationParams(DisconnectParams dp) {
   1456             if (VDBG) log("DcInactiveState: setEnterNotificationParams dp");
   1457             mConnectionParams = null;
   1458             mDisconnectParams = dp;
   1459             mDcFailCause = DcFailCause.NONE;
   1460         }
   1461 
   1462         // Inform all contexts of the failure cause
   1463         public void setEnterNotificationParams(DcFailCause cause) {
   1464             mConnectionParams = null;
   1465             mDisconnectParams = null;
   1466             mDcFailCause = cause;
   1467         }
   1468 
   1469         @Override
   1470         public void enter() {
   1471             mTag += 1;
   1472             if (DBG) log("DcInactiveState: enter() mTag=" + mTag);
   1473             StatsLog.write(StatsLog.MOBILE_CONNECTION_STATE_CHANGED,
   1474                     StatsLog.MOBILE_CONNECTION_STATE_CHANGED__STATE__INACTIVE,
   1475                     mPhone.getPhoneId(), mId,
   1476                     mApnSetting != null ? (long) mApnSetting.typesBitmap : 0L,
   1477                     mApnSetting != null
   1478                         ? mApnSetting.canHandleType(PhoneConstants.APN_TYPE_DEFAULT) : false);
   1479 
   1480             if (mConnectionParams != null) {
   1481                 if (DBG) {
   1482                     log("DcInactiveState: enter notifyConnectCompleted +ALL failCause="
   1483                             + mDcFailCause);
   1484                 }
   1485                 notifyConnectCompleted(mConnectionParams, mDcFailCause, true);
   1486             }
   1487             if (mDisconnectParams != null) {
   1488                 if (DBG) {
   1489                     log("DcInactiveState: enter notifyDisconnectCompleted +ALL failCause="
   1490                             + mDcFailCause);
   1491                 }
   1492                 notifyDisconnectCompleted(mDisconnectParams, true);
   1493             }
   1494             if (mDisconnectParams == null && mConnectionParams == null && mDcFailCause != null) {
   1495                 if (DBG) {
   1496                     log("DcInactiveState: enter notifyAllDisconnectCompleted failCause="
   1497                             + mDcFailCause);
   1498                 }
   1499                 notifyAllDisconnectCompleted(mDcFailCause);
   1500             }
   1501 
   1502             // Remove ourselves from cid mapping, before clearSettings
   1503             mDcController.removeActiveDcByCid(DataConnection.this);
   1504 
   1505             clearSettings();
   1506         }
   1507 
   1508         @Override
   1509         public void exit() {
   1510         }
   1511 
   1512         @Override
   1513         public boolean processMessage(Message msg) {
   1514             boolean retVal;
   1515 
   1516             switch (msg.what) {
   1517                 case DcAsyncChannel.REQ_RESET:
   1518                     if (DBG) {
   1519                         log("DcInactiveState: msg.what=RSP_RESET, ignore we're already reset");
   1520                     }
   1521                     retVal = HANDLED;
   1522                     break;
   1523 
   1524                 case EVENT_CONNECT:
   1525                     if (DBG) log("DcInactiveState: mag.what=EVENT_CONNECT");
   1526                     ConnectionParams cp = (ConnectionParams) msg.obj;
   1527                     if (initConnection(cp)) {
   1528                         onConnect(mConnectionParams);
   1529                         transitionTo(mActivatingState);
   1530                     } else {
   1531                         if (DBG) {
   1532                             log("DcInactiveState: msg.what=EVENT_CONNECT initConnection failed");
   1533                         }
   1534                         notifyConnectCompleted(cp, DcFailCause.UNACCEPTABLE_NETWORK_PARAMETER,
   1535                                 false);
   1536                     }
   1537                     retVal = HANDLED;
   1538                     break;
   1539 
   1540                 case EVENT_DISCONNECT:
   1541                     if (DBG) log("DcInactiveState: msg.what=EVENT_DISCONNECT");
   1542                     notifyDisconnectCompleted((DisconnectParams)msg.obj, false);
   1543                     retVal = HANDLED;
   1544                     break;
   1545 
   1546                 case EVENT_DISCONNECT_ALL:
   1547                     if (DBG) log("DcInactiveState: msg.what=EVENT_DISCONNECT_ALL");
   1548                     notifyDisconnectCompleted((DisconnectParams)msg.obj, false);
   1549                     retVal = HANDLED;
   1550                     break;
   1551 
   1552                 default:
   1553                     if (VDBG) {
   1554                         log("DcInactiveState nothandled msg.what=" + getWhatToString(msg.what));
   1555                     }
   1556                     retVal = NOT_HANDLED;
   1557                     break;
   1558             }
   1559             return retVal;
   1560         }
   1561     }
   1562     private DcInactiveState mInactiveState = new DcInactiveState();
   1563 
   1564     /**
   1565      * The state machine is activating a connection.
   1566      */
   1567     private class DcActivatingState extends State {
   1568         @Override
   1569         public void enter() {
   1570             StatsLog.write(StatsLog.MOBILE_CONNECTION_STATE_CHANGED,
   1571                     StatsLog.MOBILE_CONNECTION_STATE_CHANGED__STATE__ACTIVATING,
   1572                     mPhone.getPhoneId(), mId,
   1573                     mApnSetting != null ? (long) mApnSetting.typesBitmap : 0L,
   1574                     mApnSetting != null
   1575                         ? mApnSetting.canHandleType(PhoneConstants.APN_TYPE_DEFAULT) : false);
   1576         }
   1577         @Override
   1578         public boolean processMessage(Message msg) {
   1579             boolean retVal;
   1580             AsyncResult ar;
   1581             ConnectionParams cp;
   1582 
   1583             if (DBG) log("DcActivatingState: msg=" + msgToString(msg));
   1584             switch (msg.what) {
   1585                 case EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED:
   1586                 case EVENT_CONNECT:
   1587                     // Activating can't process until we're done.
   1588                     deferMessage(msg);
   1589                     retVal = HANDLED;
   1590                     break;
   1591 
   1592                 case EVENT_SETUP_DATA_CONNECTION_DONE:
   1593                     cp = (ConnectionParams) msg.obj;
   1594 
   1595                     DataCallResponse dataCallResponse =
   1596                             msg.getData().getParcelable(DataServiceManager.DATA_CALL_RESPONSE);
   1597                     SetupResult result = onSetupConnectionCompleted(msg.arg1, dataCallResponse, cp);
   1598                     if (result != SetupResult.ERROR_STALE) {
   1599                         if (mConnectionParams != cp) {
   1600                             loge("DcActivatingState: WEIRD mConnectionsParams:"+ mConnectionParams
   1601                                     + " != cp:" + cp);
   1602                         }
   1603                     }
   1604                     if (DBG) {
   1605                         log("DcActivatingState onSetupConnectionCompleted result=" + result
   1606                                 + " dc=" + DataConnection.this);
   1607                     }
   1608                     if (cp.mApnContext != null) {
   1609                         cp.mApnContext.requestLog("onSetupConnectionCompleted result=" + result);
   1610                     }
   1611                     switch (result) {
   1612                         case SUCCESS:
   1613                             // All is well
   1614                             mDcFailCause = DcFailCause.NONE;
   1615                             transitionTo(mActiveState);
   1616                             break;
   1617                         case ERROR_RADIO_NOT_AVAILABLE:
   1618                             // Vendor ril rejected the command and didn't connect.
   1619                             // Transition to inactive but send notifications after
   1620                             // we've entered the mInactive state.
   1621                             mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
   1622                             transitionTo(mInactiveState);
   1623                             break;
   1624                         case ERROR_INVALID_ARG:
   1625                             // The addresses given from the RIL are bad
   1626                             tearDownData(cp);
   1627                             transitionTo(mDisconnectingErrorCreatingConnection);
   1628                             break;
   1629                         case ERROR_DATA_SERVICE_SPECIFIC_ERROR:
   1630 
   1631                             // Retrieve the suggested retry delay from the modem and save it.
   1632                             // If the modem want us to retry the current APN again, it will
   1633                             // suggest a positive delay value (in milliseconds). Otherwise we'll get
   1634                             // NO_SUGGESTED_RETRY_DELAY here.
   1635 
   1636                             long delay = getSuggestedRetryDelay(dataCallResponse);
   1637                             cp.mApnContext.setModemSuggestedDelay(delay);
   1638 
   1639                             String str = "DcActivatingState: ERROR_DATA_SERVICE_SPECIFIC_ERROR "
   1640                                     + " delay=" + delay
   1641                                     + " result=" + result
   1642                                     + " result.isRestartRadioFail=" +
   1643                                     result.mFailCause.isRestartRadioFail(mPhone.getContext(),
   1644                                             mPhone.getSubId())
   1645                                     + " isPermanentFailure=" +
   1646                                     mDct.isPermanentFailure(result.mFailCause);
   1647                             if (DBG) log(str);
   1648                             if (cp.mApnContext != null) cp.mApnContext.requestLog(str);
   1649 
   1650                             // Save the cause. DcTracker.onDataSetupComplete will check this
   1651                             // failure cause and determine if we need to retry this APN later
   1652                             // or not.
   1653                             mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
   1654                             transitionTo(mInactiveState);
   1655                             break;
   1656                         case ERROR_STALE:
   1657                             loge("DcActivatingState: stale EVENT_SETUP_DATA_CONNECTION_DONE"
   1658                                     + " tag:" + cp.mTag + " != mTag:" + mTag);
   1659                             break;
   1660                         default:
   1661                             throw new RuntimeException("Unknown SetupResult, should not happen");
   1662                     }
   1663                     retVal = HANDLED;
   1664                     break;
   1665                 default:
   1666                     if (VDBG) {
   1667                         log("DcActivatingState not handled msg.what=" +
   1668                                 getWhatToString(msg.what) + " RefCount=" + mApnContexts.size());
   1669                     }
   1670                     retVal = NOT_HANDLED;
   1671                     break;
   1672             }
   1673             return retVal;
   1674         }
   1675     }
   1676     private DcActivatingState mActivatingState = new DcActivatingState();
   1677 
   1678     /**
   1679      * The state machine is connected, expecting an EVENT_DISCONNECT.
   1680      */
   1681     private class DcActiveState extends State {
   1682 
   1683         @Override public void enter() {
   1684             if (DBG) log("DcActiveState: enter dc=" + DataConnection.this);
   1685             StatsLog.write(StatsLog.MOBILE_CONNECTION_STATE_CHANGED,
   1686                     StatsLog.MOBILE_CONNECTION_STATE_CHANGED__STATE__ACTIVE,
   1687                     mPhone.getPhoneId(), mId,
   1688                     mApnSetting != null ? (long) mApnSetting.typesBitmap : 0L,
   1689                     mApnSetting != null
   1690                         ? mApnSetting.canHandleType(PhoneConstants.APN_TYPE_DEFAULT) : false);
   1691 
   1692             updateNetworkInfo();
   1693 
   1694             // If we were retrying there maybe more than one, otherwise they'll only be one.
   1695             notifyAllOfConnected(Phone.REASON_CONNECTED);
   1696 
   1697             mPhone.getCallTracker().registerForVoiceCallStarted(getHandler(),
   1698                     DataConnection.EVENT_DATA_CONNECTION_VOICE_CALL_STARTED, null);
   1699             mPhone.getCallTracker().registerForVoiceCallEnded(getHandler(),
   1700                     DataConnection.EVENT_DATA_CONNECTION_VOICE_CALL_ENDED, null);
   1701 
   1702             // If the EVENT_CONNECT set the current max retry restore it here
   1703             // if it didn't then this is effectively a NOP.
   1704             mDcController.addActiveDcByCid(DataConnection.this);
   1705 
   1706             mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED,
   1707                     mNetworkInfo.getReason(), null);
   1708             mNetworkInfo.setExtraInfo(mApnSetting.apn);
   1709             updateTcpBufferSizes(mRilRat);
   1710 
   1711             final NetworkMisc misc = new NetworkMisc();
   1712             final CarrierSignalAgent carrierSignalAgent = mPhone.getCarrierSignalAgent();
   1713             if (carrierSignalAgent.hasRegisteredReceivers(TelephonyIntents
   1714                     .ACTION_CARRIER_SIGNAL_REDIRECTED)) {
   1715                 // carrierSignal Receivers will place the carrier-specific provisioning notification
   1716                 misc.provisioningNotificationDisabled = true;
   1717             }
   1718             misc.subscriberId = mPhone.getSubscriberId();
   1719 
   1720             setNetworkRestriction();
   1721             if (DBG) log("mRestrictedNetworkOverride = " + mRestrictedNetworkOverride);
   1722             mNetworkAgent = new DcNetworkAgent(getHandler().getLooper(), mPhone.getContext(),
   1723                     "DcNetworkAgent", mNetworkInfo, getNetworkCapabilities(), mLinkProperties,
   1724                     50, misc);
   1725             mPhone.mCi.registerForNattKeepaliveStatus(
   1726                     getHandler(), DataConnection.EVENT_KEEPALIVE_STATUS, null);
   1727             mPhone.mCi.registerForLceInfo(
   1728                     getHandler(), DataConnection.EVENT_LINK_CAPACITY_CHANGED, null);
   1729         }
   1730 
   1731         @Override
   1732         public void exit() {
   1733             if (DBG) log("DcActiveState: exit dc=" + this);
   1734             String reason = mNetworkInfo.getReason();
   1735             if(mDcController.isExecutingCarrierChange()) {
   1736                 reason = Phone.REASON_CARRIER_CHANGE;
   1737             } else if (mDisconnectParams != null && mDisconnectParams.mReason != null) {
   1738                 reason = mDisconnectParams.mReason;
   1739             } else if (mDcFailCause != null) {
   1740                 reason = mDcFailCause.toString();
   1741             }
   1742             mPhone.getCallTracker().unregisterForVoiceCallStarted(getHandler());
   1743             mPhone.getCallTracker().unregisterForVoiceCallEnded(getHandler());
   1744 
   1745             mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
   1746                     reason, mNetworkInfo.getExtraInfo());
   1747             mPhone.mCi.unregisterForNattKeepaliveStatus(getHandler());
   1748             mPhone.mCi.unregisterForLceInfo(getHandler());
   1749             if (mNetworkAgent != null) {
   1750                 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
   1751                 mNetworkAgent = null;
   1752             }
   1753         }
   1754 
   1755         @Override
   1756         public boolean processMessage(Message msg) {
   1757             boolean retVal;
   1758 
   1759             switch (msg.what) {
   1760                 case EVENT_CONNECT: {
   1761                     ConnectionParams cp = (ConnectionParams) msg.obj;
   1762                     // either add this new apn context to our set or
   1763                     // update the existing cp with the latest connection generation number
   1764                     mApnContexts.put(cp.mApnContext, cp);
   1765                     if (DBG) {
   1766                         log("DcActiveState: EVENT_CONNECT cp=" + cp + " dc=" + DataConnection.this);
   1767                     }
   1768                     notifyConnectCompleted(cp, DcFailCause.NONE, false);
   1769                     retVal = HANDLED;
   1770                     break;
   1771                 }
   1772                 case EVENT_DISCONNECT: {
   1773                     DisconnectParams dp = (DisconnectParams) msg.obj;
   1774                     if (DBG) {
   1775                         log("DcActiveState: EVENT_DISCONNECT dp=" + dp
   1776                                 + " dc=" + DataConnection.this);
   1777                     }
   1778                     if (mApnContexts.containsKey(dp.mApnContext)) {
   1779                         if (DBG) {
   1780                             log("DcActiveState msg.what=EVENT_DISCONNECT RefCount="
   1781                                     + mApnContexts.size());
   1782                         }
   1783 
   1784                         if (mApnContexts.size() == 1) {
   1785                             mApnContexts.clear();
   1786                             mDisconnectParams = dp;
   1787                             mConnectionParams = null;
   1788                             dp.mTag = mTag;
   1789                             tearDownData(dp);
   1790                             transitionTo(mDisconnectingState);
   1791                         } else {
   1792                             mApnContexts.remove(dp.mApnContext);
   1793                             notifyDisconnectCompleted(dp, false);
   1794                         }
   1795                     } else {
   1796                         log("DcActiveState ERROR no such apnContext=" + dp.mApnContext
   1797                                 + " in this dc=" + DataConnection.this);
   1798                         notifyDisconnectCompleted(dp, false);
   1799                     }
   1800                     retVal = HANDLED;
   1801                     break;
   1802                 }
   1803                 case EVENT_DISCONNECT_ALL: {
   1804                     if (DBG) {
   1805                         log("DcActiveState EVENT_DISCONNECT clearing apn contexts,"
   1806                                 + " dc=" + DataConnection.this);
   1807                     }
   1808                     DisconnectParams dp = (DisconnectParams) msg.obj;
   1809                     mDisconnectParams = dp;
   1810                     mConnectionParams = null;
   1811                     dp.mTag = mTag;
   1812                     tearDownData(dp);
   1813                     transitionTo(mDisconnectingState);
   1814                     retVal = HANDLED;
   1815                     break;
   1816                 }
   1817                 case EVENT_LOST_CONNECTION: {
   1818                     if (DBG) {
   1819                         log("DcActiveState EVENT_LOST_CONNECTION dc=" + DataConnection.this);
   1820                     }
   1821 
   1822                     mInactiveState.setEnterNotificationParams(DcFailCause.LOST_CONNECTION);
   1823                     transitionTo(mInactiveState);
   1824                     retVal = HANDLED;
   1825                     break;
   1826                 }
   1827                 case EVENT_DATA_CONNECTION_ROAM_ON:
   1828                 case EVENT_DATA_CONNECTION_ROAM_OFF:
   1829                 case EVENT_DATA_CONNECTION_OVERRIDE_CHANGED: {
   1830                     updateNetworkInfo();
   1831                     if (mNetworkAgent != null) {
   1832                         mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities());
   1833                         mNetworkAgent.sendNetworkInfo(mNetworkInfo);
   1834                     }
   1835                     retVal = HANDLED;
   1836                     break;
   1837                 }
   1838                 case EVENT_BW_REFRESH_RESPONSE: {
   1839                     AsyncResult ar = (AsyncResult)msg.obj;
   1840                     if (ar.exception != null) {
   1841                         log("EVENT_BW_REFRESH_RESPONSE: error ignoring, e=" + ar.exception);
   1842                     } else {
   1843                         final LinkCapacityEstimate lce = (LinkCapacityEstimate) ar.result;
   1844                         NetworkCapabilities nc = getNetworkCapabilities();
   1845                         if (mPhone.getLceStatus() == RILConstants.LCE_ACTIVE) {
   1846                             nc.setLinkDownstreamBandwidthKbps(lce.downlinkCapacityKbps);
   1847                             if (mNetworkAgent != null) {
   1848                                 mNetworkAgent.sendNetworkCapabilities(nc);
   1849                             }
   1850                         }
   1851                     }
   1852                     retVal = HANDLED;
   1853                     break;
   1854                 }
   1855                 case EVENT_DATA_CONNECTION_VOICE_CALL_STARTED:
   1856                 case EVENT_DATA_CONNECTION_VOICE_CALL_ENDED: {
   1857                     updateNetworkInfo();
   1858                     updateNetworkInfoSuspendState();
   1859                     if (mNetworkAgent != null) {
   1860                         mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities());
   1861                         mNetworkAgent.sendNetworkInfo(mNetworkInfo);
   1862                     }
   1863                     retVal = HANDLED;
   1864                     break;
   1865                 }
   1866                 case EVENT_KEEPALIVE_START_REQUEST: {
   1867                     KeepalivePacketData pkt = (KeepalivePacketData) msg.obj;
   1868                     int slotId = msg.arg1;
   1869                     int intervalMillis = msg.arg2 * 1000;
   1870                     if (mDataServiceManager.getTransportType()
   1871                             == AccessNetworkConstants.TransportType.WWAN) {
   1872                         mPhone.mCi.startNattKeepalive(
   1873                                 DataConnection.this.mCid, pkt, intervalMillis,
   1874                                 DataConnection.this.obtainMessage(
   1875                                         EVENT_KEEPALIVE_STARTED, slotId, 0, null));
   1876                     } else {
   1877                         // We currently do not support NATT Keepalive requests using the
   1878                         // DataService API, so unless the request is WWAN (always bound via
   1879                         // the CommandsInterface), the request cannot be honored.
   1880                         //
   1881                         // TODO: b/72331356 to add support for Keepalive to the DataService
   1882                         // so that keepalive requests can be handled (if supported) by the
   1883                         // underlying transport.
   1884                         if (mNetworkAgent != null) {
   1885                             mNetworkAgent.onPacketKeepaliveEvent(
   1886                                     msg.arg1,
   1887                                     ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
   1888                         }
   1889                     }
   1890                     retVal = HANDLED;
   1891                     break;
   1892                 }
   1893                 case EVENT_KEEPALIVE_STOP_REQUEST: {
   1894                     int slotId = msg.arg1;
   1895                     int handle = mNetworkAgent.keepaliveTracker.getHandleForSlot(slotId);
   1896                     if (handle < 0) {
   1897                         loge("No slot found for stopPacketKeepalive! " + slotId);
   1898                         retVal = HANDLED;
   1899                         break;
   1900                     } else {
   1901                         logd("Stopping keepalive with handle: " + handle);
   1902                     }
   1903 
   1904                     mPhone.mCi.stopNattKeepalive(
   1905                             handle, DataConnection.this.obtainMessage(
   1906                                     EVENT_KEEPALIVE_STOPPED, handle, slotId, null));
   1907                     retVal = HANDLED;
   1908                     break;
   1909                 }
   1910                 case EVENT_KEEPALIVE_STARTED: {
   1911                     AsyncResult ar = (AsyncResult) msg.obj;
   1912                     final int slot = msg.arg1;
   1913                     if (ar.exception != null || ar.result == null) {
   1914                         loge("EVENT_KEEPALIVE_STARTED: error starting keepalive, e="
   1915                                 + ar.exception);
   1916                         mNetworkAgent.onPacketKeepaliveEvent(
   1917                                 slot, ConnectivityManager.PacketKeepalive.ERROR_HARDWARE_ERROR);
   1918                     } else {
   1919                         KeepaliveStatus ks = (KeepaliveStatus) ar.result;
   1920                         if (ks == null) {
   1921                             loge("Null KeepaliveStatus received!");
   1922                         } else {
   1923                             mNetworkAgent.keepaliveTracker.handleKeepaliveStarted(slot, ks);
   1924                         }
   1925                     }
   1926                     retVal = HANDLED;
   1927                     break;
   1928                 }
   1929                 case EVENT_KEEPALIVE_STATUS: {
   1930                     AsyncResult ar = (AsyncResult) msg.obj;
   1931                     if (ar.exception != null) {
   1932                         loge("EVENT_KEEPALIVE_STATUS: error in keepalive, e=" + ar.exception);
   1933                         // We have no way to notify connectivity in this case.
   1934                     }
   1935                     if (ar.result != null) {
   1936                         KeepaliveStatus ks = (KeepaliveStatus) ar.result;
   1937                         mNetworkAgent.keepaliveTracker.handleKeepaliveStatus(ks);
   1938                     }
   1939 
   1940                     retVal = HANDLED;
   1941                     break;
   1942                 }
   1943                 case EVENT_KEEPALIVE_STOPPED: {
   1944                     AsyncResult ar = (AsyncResult) msg.obj;
   1945                     final int handle = msg.arg1;
   1946                     final int slotId = msg.arg2;
   1947 
   1948                     if (ar.exception != null) {
   1949                         loge("EVENT_KEEPALIVE_STOPPED: error stopping keepalive for handle="
   1950                                 + handle + " e=" + ar.exception);
   1951                         mNetworkAgent.keepaliveTracker.handleKeepaliveStatus(
   1952                                 new KeepaliveStatus(KeepaliveStatus.ERROR_UNKNOWN));
   1953                     } else {
   1954                         log("Keepalive Stop Requested for handle=" + handle);
   1955                         mNetworkAgent.keepaliveTracker.handleKeepaliveStatus(
   1956                                 new KeepaliveStatus(handle, KeepaliveStatus.STATUS_INACTIVE));
   1957                     }
   1958                     retVal = HANDLED;
   1959                     break;
   1960                 }
   1961                 case EVENT_LINK_CAPACITY_CHANGED: {
   1962                     AsyncResult ar = (AsyncResult) msg.obj;
   1963                     if (ar.exception != null) {
   1964                         loge("EVENT_LINK_CAPACITY_CHANGED e=" + ar.exception);
   1965                     } else {
   1966                         LinkCapacityEstimate lce = (LinkCapacityEstimate) ar.result;
   1967                         NetworkCapabilities nc = getNetworkCapabilities();
   1968                         if (lce.downlinkCapacityKbps != LinkCapacityEstimate.INVALID) {
   1969                             nc.setLinkDownstreamBandwidthKbps(lce.downlinkCapacityKbps);
   1970                         }
   1971                         if (lce.uplinkCapacityKbps != LinkCapacityEstimate.INVALID) {
   1972                             nc.setLinkUpstreamBandwidthKbps(lce.uplinkCapacityKbps);
   1973                         }
   1974                         if (mNetworkAgent != null) {
   1975                             mNetworkAgent.sendNetworkCapabilities(nc);
   1976                         }
   1977                     }
   1978                     retVal = HANDLED;
   1979                     break;
   1980                 }
   1981                 default:
   1982                     if (VDBG) {
   1983                         log("DcActiveState not handled msg.what=" + getWhatToString(msg.what));
   1984                     }
   1985                     retVal = NOT_HANDLED;
   1986                     break;
   1987             }
   1988             return retVal;
   1989         }
   1990     }
   1991     private DcActiveState mActiveState = new DcActiveState();
   1992 
   1993     /**
   1994      * The state machine is disconnecting.
   1995      */
   1996     private class DcDisconnectingState extends State {
   1997         @Override
   1998         public void enter() {
   1999             StatsLog.write(StatsLog.MOBILE_CONNECTION_STATE_CHANGED,
   2000                     StatsLog.MOBILE_CONNECTION_STATE_CHANGED__STATE__DISCONNECTING,
   2001                     mPhone.getPhoneId(), mId,
   2002                     mApnSetting != null ? (long) mApnSetting.typesBitmap : 0L,
   2003                     mApnSetting != null
   2004                         ? mApnSetting.canHandleType(PhoneConstants.APN_TYPE_DEFAULT) : false);
   2005         }
   2006         @Override
   2007         public boolean processMessage(Message msg) {
   2008             boolean retVal;
   2009 
   2010             switch (msg.what) {
   2011                 case EVENT_CONNECT:
   2012                     if (DBG) log("DcDisconnectingState msg.what=EVENT_CONNECT. Defer. RefCount = "
   2013                             + mApnContexts.size());
   2014                     deferMessage(msg);
   2015                     retVal = HANDLED;
   2016                     break;
   2017 
   2018                 case EVENT_DEACTIVATE_DONE:
   2019                     DisconnectParams dp = (DisconnectParams) msg.obj;
   2020 
   2021                     String str = "DcDisconnectingState msg.what=EVENT_DEACTIVATE_DONE RefCount="
   2022                             + mApnContexts.size();
   2023                     if (DBG) log(str);
   2024                     if (dp.mApnContext != null) dp.mApnContext.requestLog(str);
   2025 
   2026                     if (dp.mTag == mTag) {
   2027                         // Transition to inactive but send notifications after
   2028                         // we've entered the mInactive state.
   2029                         mInactiveState.setEnterNotificationParams(dp);
   2030                         transitionTo(mInactiveState);
   2031                     } else {
   2032                         if (DBG) log("DcDisconnectState stale EVENT_DEACTIVATE_DONE"
   2033                                 + " dp.tag=" + dp.mTag + " mTag=" + mTag);
   2034                     }
   2035                     retVal = HANDLED;
   2036                     break;
   2037 
   2038                 default:
   2039                     if (VDBG) {
   2040                         log("DcDisconnectingState not handled msg.what="
   2041                                 + getWhatToString(msg.what));
   2042                     }
   2043                     retVal = NOT_HANDLED;
   2044                     break;
   2045             }
   2046             return retVal;
   2047         }
   2048     }
   2049     private DcDisconnectingState mDisconnectingState = new DcDisconnectingState();
   2050 
   2051     /**
   2052      * The state machine is disconnecting after an creating a connection.
   2053      */
   2054     private class DcDisconnectionErrorCreatingConnection extends State {
   2055         @Override
   2056         public void enter() {
   2057             StatsLog.write(StatsLog.MOBILE_CONNECTION_STATE_CHANGED,
   2058                     StatsLog.MOBILE_CONNECTION_STATE_CHANGED__STATE__DISCONNECTION_ERROR_CREATING_CONNECTION,
   2059                     mPhone.getPhoneId(), mId,
   2060                     mApnSetting != null ? (long) mApnSetting.typesBitmap : 0L,
   2061                     mApnSetting != null
   2062                         ? mApnSetting.canHandleType(PhoneConstants.APN_TYPE_DEFAULT) : false);
   2063         }
   2064         @Override
   2065         public boolean processMessage(Message msg) {
   2066             boolean retVal;
   2067 
   2068             switch (msg.what) {
   2069                 case EVENT_DEACTIVATE_DONE:
   2070                     ConnectionParams cp = (ConnectionParams) msg.obj;
   2071                     if (cp.mTag == mTag) {
   2072                         String str = "DcDisconnectionErrorCreatingConnection" +
   2073                                 " msg.what=EVENT_DEACTIVATE_DONE";
   2074                         if (DBG) log(str);
   2075                         if (cp.mApnContext != null) cp.mApnContext.requestLog(str);
   2076 
   2077                         // Transition to inactive but send notifications after
   2078                         // we've entered the mInactive state.
   2079                         mInactiveState.setEnterNotificationParams(cp,
   2080                                 DcFailCause.UNACCEPTABLE_NETWORK_PARAMETER);
   2081                         transitionTo(mInactiveState);
   2082                     } else {
   2083                         if (DBG) {
   2084                             log("DcDisconnectionErrorCreatingConnection stale EVENT_DEACTIVATE_DONE"
   2085                                     + " dp.tag=" + cp.mTag + ", mTag=" + mTag);
   2086                         }
   2087                     }
   2088                     retVal = HANDLED;
   2089                     break;
   2090 
   2091                 default:
   2092                     if (VDBG) {
   2093                         log("DcDisconnectionErrorCreatingConnection not handled msg.what="
   2094                                 + getWhatToString(msg.what));
   2095                     }
   2096                     retVal = NOT_HANDLED;
   2097                     break;
   2098             }
   2099             return retVal;
   2100         }
   2101     }
   2102     private DcDisconnectionErrorCreatingConnection mDisconnectingErrorCreatingConnection =
   2103                 new DcDisconnectionErrorCreatingConnection();
   2104 
   2105 
   2106     private class DcNetworkAgent extends NetworkAgent {
   2107 
   2108         private NetworkCapabilities mNetworkCapabilities;
   2109 
   2110         public final DcKeepaliveTracker keepaliveTracker = new DcKeepaliveTracker();
   2111 
   2112         public DcNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni,
   2113                 NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
   2114             super(l, c, TAG, ni, nc, lp, score, misc);
   2115             mNetCapsLocalLog.log("New network agent created. capabilities=" + nc);
   2116             mNetworkCapabilities = nc;
   2117         }
   2118 
   2119         @Override
   2120         protected void unwanted() {
   2121             if (mNetworkAgent != this) {
   2122                 log("DcNetworkAgent: unwanted found mNetworkAgent=" + mNetworkAgent +
   2123                         ", which isn't me.  Aborting unwanted");
   2124                 return;
   2125             }
   2126             // this can only happen if our exit has been called - we're already disconnected
   2127             if (mApnContexts == null) return;
   2128             for (ConnectionParams cp : mApnContexts.values()) {
   2129                 final ApnContext apnContext = cp.mApnContext;
   2130                 final Pair<ApnContext, Integer> pair =
   2131                         new Pair<ApnContext, Integer>(apnContext, cp.mConnectionGeneration);
   2132                 log("DcNetworkAgent: [unwanted]: disconnect apnContext=" + apnContext);
   2133                 Message msg = mDct.obtainMessage(DctConstants.EVENT_DISCONNECT_DONE, pair);
   2134                 DisconnectParams dp = new DisconnectParams(apnContext, apnContext.getReason(), msg);
   2135                 DataConnection.this.sendMessage(DataConnection.this.
   2136                         obtainMessage(EVENT_DISCONNECT, dp));
   2137             }
   2138         }
   2139 
   2140         @Override
   2141         protected void pollLceData() {
   2142             if(mPhone.getLceStatus() == RILConstants.LCE_ACTIVE) {  // active LCE service
   2143                 mPhone.mCi.pullLceData(DataConnection.this.obtainMessage(EVENT_BW_REFRESH_RESPONSE));
   2144             }
   2145         }
   2146 
   2147         @Override
   2148         protected void networkStatus(int status, String redirectUrl) {
   2149             if(!TextUtils.isEmpty(redirectUrl)) {
   2150                 log("validation status: " + status + " with redirection URL: " + redirectUrl);
   2151                 /* its possible that we have multiple DataConnection with INTERNET_CAPABILITY
   2152                    all fail the validation with the same redirection url, send CMD back to DCTracker
   2153                    and let DcTracker to make the decision */
   2154                 Message msg = mDct.obtainMessage(DctConstants.EVENT_REDIRECTION_DETECTED,
   2155                         redirectUrl);
   2156                 msg.sendToTarget();
   2157             }
   2158         }
   2159 
   2160         @Override
   2161         public void sendNetworkCapabilities(NetworkCapabilities networkCapabilities) {
   2162             if (!networkCapabilities.equals(mNetworkCapabilities)) {
   2163                 String logStr = "Changed from " + mNetworkCapabilities + " to "
   2164                         + networkCapabilities + ", Data RAT="
   2165                         + mPhone.getServiceState().getRilDataRadioTechnology()
   2166                         + ", mApnSetting=" + mApnSetting;
   2167                 mNetCapsLocalLog.log(logStr);
   2168                 log(logStr);
   2169                 mNetworkCapabilities = networkCapabilities;
   2170             }
   2171             super.sendNetworkCapabilities(networkCapabilities);
   2172         }
   2173 
   2174         @Override
   2175         protected void startPacketKeepalive(Message msg) {
   2176             DataConnection.this.obtainMessage(EVENT_KEEPALIVE_START_REQUEST,
   2177                     msg.arg1, msg.arg2, msg.obj).sendToTarget();
   2178         }
   2179 
   2180         @Override
   2181         protected void stopPacketKeepalive(Message msg) {
   2182             DataConnection.this.obtainMessage(EVENT_KEEPALIVE_STOP_REQUEST,
   2183                     msg.arg1, msg.arg2, msg.obj).sendToTarget();
   2184         }
   2185 
   2186         private class DcKeepaliveTracker {
   2187             private class KeepaliveRecord {
   2188                 public int slotId;
   2189                 public int currentStatus;
   2190 
   2191                 KeepaliveRecord(int slotId, int status) {
   2192                     this.slotId = slotId;
   2193                     this.currentStatus = status;
   2194                 }
   2195             };
   2196 
   2197             private final SparseArray<KeepaliveRecord> mKeepalives = new SparseArray();
   2198 
   2199             int getHandleForSlot(int slotId) {
   2200                 for (int i = 0; i < mKeepalives.size(); i++) {
   2201                     KeepaliveRecord kr = mKeepalives.valueAt(i);
   2202                     if (kr.slotId == slotId) return mKeepalives.keyAt(i);
   2203                 }
   2204                 return -1;
   2205             }
   2206 
   2207             int keepaliveStatusErrorToPacketKeepaliveError(int error) {
   2208                 switch(error) {
   2209                     case KeepaliveStatus.ERROR_NONE:
   2210                         return PacketKeepalive.SUCCESS;
   2211                     case KeepaliveStatus.ERROR_UNSUPPORTED:
   2212                         return PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
   2213                     case KeepaliveStatus.ERROR_NO_RESOURCES:
   2214                     case KeepaliveStatus.ERROR_UNKNOWN:
   2215                     default:
   2216                         return PacketKeepalive.ERROR_HARDWARE_ERROR;
   2217                 }
   2218             }
   2219 
   2220             void handleKeepaliveStarted(final int slot, KeepaliveStatus ks) {
   2221                 switch (ks.statusCode) {
   2222                     case KeepaliveStatus.STATUS_INACTIVE:
   2223                         DcNetworkAgent.this.onPacketKeepaliveEvent(slot,
   2224                                 keepaliveStatusErrorToPacketKeepaliveError(ks.errorCode));
   2225                         break;
   2226                     case KeepaliveStatus.STATUS_ACTIVE:
   2227                         DcNetworkAgent.this.onPacketKeepaliveEvent(
   2228                                 slot, PacketKeepalive.SUCCESS);
   2229                         // fall through to add record
   2230                     case KeepaliveStatus.STATUS_PENDING:
   2231                         log("Adding keepalive handle="
   2232                                 + ks.sessionHandle + " slot = " + slot);
   2233                         mKeepalives.put(ks.sessionHandle,
   2234                                 new KeepaliveRecord(
   2235                                         slot, ks.statusCode));
   2236                         break;
   2237                     default:
   2238                         loge("Invalid KeepaliveStatus Code: " + ks.statusCode);
   2239                         break;
   2240                 }
   2241             }
   2242 
   2243             void handleKeepaliveStatus(KeepaliveStatus ks) {
   2244                 final KeepaliveRecord kr;
   2245                 kr = mKeepalives.get(ks.sessionHandle);
   2246 
   2247                 if (kr == null) {
   2248                     // If there is no slot for the session handle, we received an event
   2249                     // for a different data connection. This is not an error because the
   2250                     // keepalive session events are broadcast to all listeners.
   2251                     log("Discarding keepalive event for different data connection:" + ks);
   2252                     return;
   2253                 }
   2254                 // Switch on the current state, to see what we do with the status update
   2255                 switch (kr.currentStatus) {
   2256                     case KeepaliveStatus.STATUS_INACTIVE:
   2257                         loge("Inactive Keepalive received status!");
   2258                         DcNetworkAgent.this.onPacketKeepaliveEvent(
   2259                                 kr.slotId, PacketKeepalive.ERROR_HARDWARE_ERROR);
   2260                         break;
   2261                     case KeepaliveStatus.STATUS_PENDING:
   2262                         switch (ks.statusCode) {
   2263                             case KeepaliveStatus.STATUS_INACTIVE:
   2264                                 DcNetworkAgent.this.onPacketKeepaliveEvent(kr.slotId,
   2265                                         keepaliveStatusErrorToPacketKeepaliveError(ks.errorCode));
   2266                                 kr.currentStatus = KeepaliveStatus.STATUS_INACTIVE;
   2267                                 mKeepalives.remove(ks.sessionHandle);
   2268                                 break;
   2269                             case KeepaliveStatus.STATUS_ACTIVE:
   2270                                 log("Pending Keepalive received active status!");
   2271                                 kr.currentStatus = KeepaliveStatus.STATUS_ACTIVE;
   2272                                 DcNetworkAgent.this.onPacketKeepaliveEvent(
   2273                                         kr.slotId, PacketKeepalive.SUCCESS);
   2274                                 break;
   2275                             case KeepaliveStatus.STATUS_PENDING:
   2276                                 loge("Invalid unsolicied Keepalive Pending Status!");
   2277                                 break;
   2278                             default:
   2279                                 loge("Invalid Keepalive Status received, " + ks.statusCode);
   2280                         }
   2281                         break;
   2282                     case KeepaliveStatus.STATUS_ACTIVE:
   2283                         switch (ks.statusCode) {
   2284                             case KeepaliveStatus.STATUS_INACTIVE:
   2285                                 loge("Keepalive received stopped status!");
   2286                                 DcNetworkAgent.this.onPacketKeepaliveEvent(
   2287                                         kr.slotId, PacketKeepalive.SUCCESS);
   2288                                 kr.currentStatus = KeepaliveStatus.STATUS_INACTIVE;
   2289                                 mKeepalives.remove(ks.sessionHandle);
   2290                                 break;
   2291                             case KeepaliveStatus.STATUS_PENDING:
   2292                             case KeepaliveStatus.STATUS_ACTIVE:
   2293                                 loge("Active Keepalive received invalid status!");
   2294                                 break;
   2295                             default:
   2296                                 loge("Invalid Keepalive Status received, " + ks.statusCode);
   2297                         }
   2298                         break;
   2299                     default:
   2300                         loge("Invalid Keepalive Status received, " + kr.currentStatus);
   2301                 }
   2302             }
   2303         };
   2304     }
   2305 
   2306     // ******* "public" interface
   2307 
   2308     /**
   2309      * Used for testing purposes.
   2310      */
   2311     /* package */ void tearDownNow() {
   2312         if (DBG) log("tearDownNow()");
   2313         sendMessage(obtainMessage(EVENT_TEAR_DOWN_NOW));
   2314     }
   2315 
   2316     /**
   2317      * Using the result of the SETUP_DATA_CALL determine the retry delay.
   2318      *
   2319      * @param response The response from setup data call
   2320      * @return NO_SUGGESTED_RETRY_DELAY if no retry is needed otherwise the delay to the
   2321      *         next SETUP_DATA_CALL
   2322      */
   2323     private long getSuggestedRetryDelay(DataCallResponse response) {
   2324         /** According to ril.h
   2325          * The value < 0 means no value is suggested
   2326          * The value 0 means retry should be done ASAP.
   2327          * The value of Integer.MAX_VALUE(0x7fffffff) means no retry.
   2328          */
   2329 
   2330         // The value < 0 means no value is suggested
   2331         if (response.getSuggestedRetryTime() < 0) {
   2332             if (DBG) log("No suggested retry delay.");
   2333             return RetryManager.NO_SUGGESTED_RETRY_DELAY;
   2334         }
   2335         // The value of Integer.MAX_VALUE(0x7fffffff) means no retry.
   2336         else if (response.getSuggestedRetryTime() == Integer.MAX_VALUE) {
   2337             if (DBG) log("Modem suggested not retrying.");
   2338             return RetryManager.NO_RETRY;
   2339         }
   2340 
   2341         // We need to cast it to long because the value returned from RIL is a 32-bit integer,
   2342         // but the time values used in AlarmManager are all 64-bit long.
   2343         return (long) response.getSuggestedRetryTime();
   2344     }
   2345 
   2346     /**
   2347      * @return the string for msg.what as our info.
   2348      */
   2349     @Override
   2350     protected String getWhatToString(int what) {
   2351         return cmdToString(what);
   2352     }
   2353 
   2354     private static String msgToString(Message msg) {
   2355         String retVal;
   2356         if (msg == null) {
   2357             retVal = "null";
   2358         } else {
   2359             StringBuilder   b = new StringBuilder();
   2360 
   2361             b.append("{what=");
   2362             b.append(cmdToString(msg.what));
   2363 
   2364             b.append(" when=");
   2365             TimeUtils.formatDuration(msg.getWhen() - SystemClock.uptimeMillis(), b);
   2366 
   2367             if (msg.arg1 != 0) {
   2368                 b.append(" arg1=");
   2369                 b.append(msg.arg1);
   2370             }
   2371 
   2372             if (msg.arg2 != 0) {
   2373                 b.append(" arg2=");
   2374                 b.append(msg.arg2);
   2375             }
   2376 
   2377             if (msg.obj != null) {
   2378                 b.append(" obj=");
   2379                 b.append(msg.obj);
   2380             }
   2381 
   2382             b.append(" target=");
   2383             b.append(msg.getTarget());
   2384 
   2385             b.append(" replyTo=");
   2386             b.append(msg.replyTo);
   2387 
   2388             b.append("}");
   2389 
   2390             retVal = b.toString();
   2391         }
   2392         return retVal;
   2393     }
   2394 
   2395     static void slog(String s) {
   2396         Rlog.d("DC", s);
   2397     }
   2398 
   2399     /**
   2400      * Log with debug
   2401      *
   2402      * @param s is string log
   2403      */
   2404     @Override
   2405     protected void log(String s) {
   2406         Rlog.d(getName(), s);
   2407     }
   2408 
   2409     /**
   2410      * Log with debug attribute
   2411      *
   2412      * @param s is string log
   2413      */
   2414     @Override
   2415     protected void logd(String s) {
   2416         Rlog.d(getName(), s);
   2417     }
   2418 
   2419     /**
   2420      * Log with verbose attribute
   2421      *
   2422      * @param s is string log
   2423      */
   2424     @Override
   2425     protected void logv(String s) {
   2426         Rlog.v(getName(), s);
   2427     }
   2428 
   2429     /**
   2430      * Log with info attribute
   2431      *
   2432      * @param s is string log
   2433      */
   2434     @Override
   2435     protected void logi(String s) {
   2436         Rlog.i(getName(), s);
   2437     }
   2438 
   2439     /**
   2440      * Log with warning attribute
   2441      *
   2442      * @param s is string log
   2443      */
   2444     @Override
   2445     protected void logw(String s) {
   2446         Rlog.w(getName(), s);
   2447     }
   2448 
   2449     /**
   2450      * Log with error attribute
   2451      *
   2452      * @param s is string log
   2453      */
   2454     @Override
   2455     protected void loge(String s) {
   2456         Rlog.e(getName(), s);
   2457     }
   2458 
   2459     /**
   2460      * Log with error attribute
   2461      *
   2462      * @param s is string log
   2463      * @param e is a Throwable which logs additional information.
   2464      */
   2465     @Override
   2466     protected void loge(String s, Throwable e) {
   2467         Rlog.e(getName(), s, e);
   2468     }
   2469 
   2470     /** Doesn't print mApnList of ApnContext's which would be recursive */
   2471     public String toStringSimple() {
   2472         return getName() + ": State=" + getCurrentState().getName()
   2473                 + " mApnSetting=" + mApnSetting + " RefCount=" + mApnContexts.size()
   2474                 + " mCid=" + mCid + " mCreateTime=" + mCreateTime
   2475                 + " mLastastFailTime=" + mLastFailTime
   2476                 + " mLastFailCause=" + mLastFailCause
   2477                 + " mTag=" + mTag
   2478                 + " mLinkProperties=" + mLinkProperties
   2479                 + " linkCapabilities=" + getNetworkCapabilities()
   2480                 + " mRestrictedNetworkOverride=" + mRestrictedNetworkOverride;
   2481     }
   2482 
   2483     @Override
   2484     public String toString() {
   2485         return "{" + toStringSimple() + " mApnContexts=" + mApnContexts + "}";
   2486     }
   2487 
   2488     private void dumpToLog() {
   2489         dump(null, new PrintWriter(new StringWriter(0)) {
   2490             @Override
   2491             public void println(String s) {
   2492                 DataConnection.this.logd(s);
   2493             }
   2494 
   2495             @Override
   2496             public void flush() {
   2497             }
   2498         }, null);
   2499     }
   2500 
   2501     /**
   2502      * Dump the current state.
   2503      *
   2504      * @param fd
   2505      * @param pw
   2506      * @param args
   2507      */
   2508     @Override
   2509     public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
   2510         IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " ");
   2511         pw.print("DataConnection ");
   2512         super.dump(fd, pw, args);
   2513         pw.flush();
   2514         pw.increaseIndent();
   2515         pw.println("mApnContexts.size=" + mApnContexts.size());
   2516         pw.println("mApnContexts=" + mApnContexts);
   2517         pw.println("mDataConnectionTracker=" + mDct);
   2518         pw.println("mApnSetting=" + mApnSetting);
   2519         pw.println("mTag=" + mTag);
   2520         pw.println("mCid=" + mCid);
   2521         pw.println("mConnectionParams=" + mConnectionParams);
   2522         pw.println("mDisconnectParams=" + mDisconnectParams);
   2523         pw.println("mDcFailCause=" + mDcFailCause);
   2524         pw.println("mPhone=" + mPhone);
   2525         pw.println("mLinkProperties=" + mLinkProperties);
   2526         pw.flush();
   2527         pw.println("mDataRegState=" + mDataRegState);
   2528         pw.println("mRilRat=" + mRilRat);
   2529         pw.println("mNetworkCapabilities=" + getNetworkCapabilities());
   2530         pw.println("mCreateTime=" + TimeUtils.logTimeOfDay(mCreateTime));
   2531         pw.println("mLastFailTime=" + TimeUtils.logTimeOfDay(mLastFailTime));
   2532         pw.println("mLastFailCause=" + mLastFailCause);
   2533         pw.println("mUserData=" + mUserData);
   2534         pw.println("mSubscriptionOverride=" + Integer.toHexString(mSubscriptionOverride));
   2535         pw.println("mInstanceNumber=" + mInstanceNumber);
   2536         pw.println("mAc=" + mAc);
   2537         pw.println("Network capabilities changed history:");
   2538         pw.increaseIndent();
   2539         mNetCapsLocalLog.dump(fd, pw, args);
   2540         pw.decreaseIndent();
   2541         pw.decreaseIndent();
   2542         pw.println();
   2543         pw.flush();
   2544     }
   2545 }
   2546 
   2547