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 ConnectionParams(ApnContext apnContext, int initialMaxRetry, int profileId, int rilRadioTechnology, boolean retryWhenSSChange, Message onCompletedMsg)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 toString()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 DisconnectParams(ApnContext apnContext, String reason, Message onCompletedMsg)158 DisconnectParams(ApnContext apnContext, String reason, Message onCompletedMsg) { 159 mApnContext = apnContext; 160 mReason = reason; 161 mOnCompletedMsg = onCompletedMsg; 162 } 163 164 @Override toString()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 cmdToString(int cmd)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 */ makeDataConnection(PhoneBase phone, int id, DcTrackerBase dct, DcTesterFailBringUpAll failBringUpAll, DcController dcc)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 dispose()266 void dispose() { 267 log("dispose: call quiteNow()"); 268 quitNow(); 269 } 270 271 /* Getter functions */ 272 getCopyNetworkCapabilities()273 NetworkCapabilities getCopyNetworkCapabilities() { 274 return makeNetworkCapabilities(); 275 } 276 getCopyLinkProperties()277 LinkProperties getCopyLinkProperties() { 278 return new LinkProperties(mLinkProperties); 279 } 280 getIsInactive()281 boolean getIsInactive() { 282 return getCurrentState() == mInactiveState; 283 } 284 getCid()285 int getCid() { 286 return mCid; 287 } 288 getApnSetting()289 ApnSetting getApnSetting() { 290 return mApnSetting; 291 } 292 setLinkPropertiesHttpProxy(ProxyInfo proxy)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; UpdateLinkPropertyResult(LinkProperties curLp)301 public UpdateLinkPropertyResult(LinkProperties curLp) { 302 oldLp = curLp; 303 newLp = curLp; 304 } 305 } 306 isIpv4Connected()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 isIpv6Connected()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 updateLinkProperty(DataCallResponse newState)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 */ checkSetMtu(ApnSetting apn, LinkProperties lp)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) DataConnection(PhoneBase phone, String name, int id, DcTrackerBase dct, DcTesterFailBringUpAll failBringUpAll, DcController dcc)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 getRetryConfig(boolean forDefault)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 configureRetry(boolean forDefault)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 */ onConnect(ConnectionParams cp)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 */ tearDownData(Object o)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 notifyAllWithEvent(ApnContext alreadySent, int event, String reason)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 notifyAllOfConnected(String reason)607 private void notifyAllOfConnected(String reason) { 608 notifyAllWithEvent(null, DctConstants.EVENT_DATA_SETUP_COMPLETE, reason); 609 } 610 notifyAllOfDisconnectDcRetrying(String reason)611 private void notifyAllOfDisconnectDcRetrying(String reason) { 612 notifyAllWithEvent(null, DctConstants.EVENT_DISCONNECT_DC_RETRYING, reason); 613 } notifyAllDisconnectCompleted(DcFailCause cause)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 */ notifyConnectCompleted(ConnectionParams cp, DcFailCause cause, boolean sendAll)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 */ notifyDisconnectCompleted(DisconnectParams dp, boolean sendAll)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 */ getDataConnectionId()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 */ clearSettings()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 */ onSetupConnectionCompleted(AsyncResult ar)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 isDnsOk(String[] domainNameServers)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 updateTcpBufferSizes(int rilRat)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 makeNetworkCapabilities()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 isIpAddress(String address)977 private boolean isIpAddress(String address) { 978 if (address == null) return false; 979 980 return Patterns.IP_ADDRESS.matcher(address).matches(); 981 } 982 setLinkProperties(DataCallResponse response, LinkProperties lp)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 */ initConnection(ConnectionParams cp)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 enter()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 exit()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 processMessage(Message msg)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 setEnterNotificationParams(ConnectionParams cp, DcFailCause cause)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 setEnterNotificationParams(DisconnectParams dp)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 setEnterNotificationParams(DcFailCause cause)1272 public void setEnterNotificationParams(DcFailCause cause) { 1273 mConnectionParams = null; 1274 mDisconnectParams = null; 1275 mDcFailCause = cause; 1276 } 1277 1278 @Override enter()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 exit()1312 public void exit() { 1313 } 1314 1315 @Override processMessage(Message msg)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 enter()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 processMessage(Message msg)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 processMessage(Message msg)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 { enter()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 exit()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 processMessage(Message msg)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 processMessage(Message msg)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 processMessage(Message msg)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 { DcNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc)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 unwanted()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 */ tearDownNow()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 getWhatToString(int what)1994 protected String getWhatToString(int what) { 1995 return cmdToString(what); 1996 } 1997 msgToString(Message msg)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 slog(String s)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 log(String s)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 logd(String s)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 logv(String s)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 logi(String s)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 logw(String s)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 loge(String s)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 loge(String s, Throwable e)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 */ toStringSimple()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 toString()2128 public String toString() { 2129 return "{" + toStringSimple() + " mApnContexts=" + mApnContexts + "}"; 2130 } 2131 dumpToLog()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 dump(FileDescriptor fd, PrintWriter pw, String[] args)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