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