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