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