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