DataConnection.java revision 2dde8b1659b1eb231e667bc19307ef294b627beb
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 17package com.android.internal.telephony.dataconnection; 18 19import com.android.internal.telephony.CallTracker; 20import com.android.internal.telephony.CommandException; 21import com.android.internal.telephony.DctConstants; 22import com.android.internal.telephony.Phone; 23import com.android.internal.telephony.PhoneBase; 24import com.android.internal.telephony.PhoneConstants; 25import com.android.internal.telephony.RILConstants; 26import com.android.internal.telephony.RetryManager; 27import com.android.internal.telephony.ServiceStateTracker; 28import com.android.internal.util.AsyncChannel; 29import com.android.internal.util.FastPrintWriter; 30import com.android.internal.util.Protocol; 31import com.android.internal.util.State; 32import com.android.internal.util.StateMachine; 33 34import android.app.PendingIntent; 35import android.content.Context; 36import android.net.ConnectivityManager; 37import android.net.LinkProperties; 38import android.net.NetworkAgent; 39import android.net.NetworkCapabilities; 40import android.net.NetworkInfo; 41import android.net.NetworkMisc; 42import android.net.ProxyInfo; 43import android.os.AsyncResult; 44import android.os.Build; 45import android.os.Looper; 46import android.os.Message; 47import android.os.Messenger; 48import android.os.SystemClock; 49import android.os.SystemProperties; 50import android.telephony.Rlog; 51import android.telephony.ServiceState; 52import android.telephony.TelephonyManager; 53import android.text.TextUtils; 54import android.util.Pair; 55import android.util.Patterns; 56import android.util.TimeUtils; 57 58import java.io.FileDescriptor; 59import java.io.OutputStream; 60import java.io.PrintWriter; 61import java.io.StringWriter; 62import java.util.ArrayList; 63import java.util.List; 64import java.util.Locale; 65import java.util.concurrent.atomic.AtomicInteger; 66import java.net.InetAddress; 67import 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 */ 87public 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().getDataRoaming()) { 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 ConnectivityManager.maybeMarkCapabilitiesRestricted(result); 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 if (DBG) log("DcActivatingState: ERR_RilError restart radio"); 1656 mDct.sendRestartRadio(); 1657 mInactiveState.setEnterNotificationParams(cp, result.mFailCause); 1658 transitionTo(mInactiveState); 1659 } else if (mDct.isPermanentFail(result.mFailCause)) { 1660 if (DBG) log("DcActivatingState: ERR_RilError perm error"); 1661 mInactiveState.setEnterNotificationParams(cp, result.mFailCause); 1662 transitionTo(mInactiveState); 1663 } else if (delay >= 0) { 1664 if (DBG) log("DcActivatingState: ERR_RilError retry"); 1665 mDcRetryAlarmController.startRetryAlarm(EVENT_RETRY_CONNECTION, 1666 mTag, delay); 1667 transitionTo(mRetryingState); 1668 } else { 1669 if (DBG) log("DcActivatingState: ERR_RilError no retry"); 1670 mInactiveState.setEnterNotificationParams(cp, result.mFailCause); 1671 transitionTo(mInactiveState); 1672 } 1673 break; 1674 case ERR_Stale: 1675 loge("DcActivatingState: stale EVENT_SETUP_DATA_CONNECTION_DONE" 1676 + " tag:" + cp.mTag + " != mTag:" + mTag); 1677 break; 1678 default: 1679 throw new RuntimeException("Unknown SetupResult, should not happen"); 1680 } 1681 retVal = HANDLED; 1682 break; 1683 1684 case EVENT_GET_LAST_FAIL_DONE: 1685 ar = (AsyncResult) msg.obj; 1686 cp = (ConnectionParams) ar.userObj; 1687 if (cp.mTag == mTag) { 1688 if (mConnectionParams != cp) { 1689 loge("DcActivatingState: WEIRD mConnectionsParams:" + mConnectionParams 1690 + " != cp:" + cp); 1691 } 1692 1693 DcFailCause cause = DcFailCause.UNKNOWN; 1694 1695 if (ar.exception == null) { 1696 int rilFailCause = ((int[]) (ar.result))[0]; 1697 cause = DcFailCause.fromInt(rilFailCause); 1698 if (cause == DcFailCause.NONE) { 1699 if (DBG) { 1700 log("DcActivatingState msg.what=EVENT_GET_LAST_FAIL_DONE" 1701 + " BAD: error was NONE, change to UNKNOWN"); 1702 } 1703 cause = DcFailCause.UNKNOWN; 1704 } 1705 } 1706 mDcFailCause = cause; 1707 1708 int retryDelay = mRetryManager.getRetryTimer(); 1709 if (DBG) { 1710 log("DcActivatingState msg.what=EVENT_GET_LAST_FAIL_DONE" 1711 + " cause=" + cause 1712 + " retryDelay=" + retryDelay 1713 + " isRetryNeeded=" + mRetryManager.isRetryNeeded() 1714 + " dc=" + DataConnection.this); 1715 } 1716 if (cause.isRestartRadioFail()) { 1717 if (DBG) { 1718 log("DcActivatingState: EVENT_GET_LAST_FAIL_DONE" 1719 + " restart radio"); 1720 } 1721 mDct.sendRestartRadio(); 1722 mInactiveState.setEnterNotificationParams(cp, cause); 1723 transitionTo(mInactiveState); 1724 } else if (mDct.isPermanentFail(cause)) { 1725 if (DBG) log("DcActivatingState: EVENT_GET_LAST_FAIL_DONE perm er"); 1726 mInactiveState.setEnterNotificationParams(cp, cause); 1727 transitionTo(mInactiveState); 1728 } else if ((retryDelay >= 0) && (mRetryManager.isRetryNeeded())) { 1729 if (DBG) log("DcActivatingState: EVENT_GET_LAST_FAIL_DONE retry"); 1730 mDcRetryAlarmController.startRetryAlarm(EVENT_RETRY_CONNECTION, mTag, 1731 retryDelay); 1732 transitionTo(mRetryingState); 1733 } else { 1734 if (DBG) log("DcActivatingState: EVENT_GET_LAST_FAIL_DONE no retry"); 1735 mInactiveState.setEnterNotificationParams(cp, cause); 1736 transitionTo(mInactiveState); 1737 } 1738 } else { 1739 loge("DcActivatingState: stale EVENT_GET_LAST_FAIL_DONE" 1740 + " tag:" + cp.mTag + " != mTag:" + mTag); 1741 } 1742 1743 retVal = HANDLED; 1744 break; 1745 1746 default: 1747 if (VDBG) { 1748 log("DcActivatingState not handled msg.what=" + 1749 getWhatToString(msg.what) + " RefCount=" + mApnContexts.size()); 1750 } 1751 retVal = NOT_HANDLED; 1752 break; 1753 } 1754 return retVal; 1755 } 1756 } 1757 private DcActivatingState mActivatingState = new DcActivatingState(); 1758 1759 /** 1760 * The state machine is connected, expecting an EVENT_DISCONNECT. 1761 */ 1762 private class DcActiveState extends State { 1763 @Override public void enter() { 1764 if (DBG) log("DcActiveState: enter dc=" + DataConnection.this); 1765 1766 if (mRetryManager.getRetryCount() != 0) { 1767 log("DcActiveState: connected after retrying call notifyAllOfConnected"); 1768 mRetryManager.setRetryCount(0); 1769 } 1770 // If we were retrying there maybe more than one, otherwise they'll only be one. 1771 notifyAllOfConnected(Phone.REASON_CONNECTED); 1772 1773 mPhone.getCallTracker().registerForVoiceCallStarted(getHandler(), 1774 DataConnection.EVENT_DATA_CONNECTION_VOICE_CALL_STARTED, null); 1775 mPhone.getCallTracker().registerForVoiceCallEnded(getHandler(), 1776 DataConnection.EVENT_DATA_CONNECTION_VOICE_CALL_ENDED, null); 1777 1778 // If the EVENT_CONNECT set the current max retry restore it here 1779 // if it didn't then this is effectively a NOP. 1780 mRetryManager.restoreCurMaxRetryCount(); 1781 mDcController.addActiveDcByCid(DataConnection.this); 1782 1783 mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, 1784 mNetworkInfo.getReason(), null); 1785 mNetworkInfo.setExtraInfo(mApnSetting.apn); 1786 updateTcpBufferSizes(mRilRat); 1787 1788 final NetworkMisc misc = new NetworkMisc(); 1789 misc.subscriberId = mPhone.getSubscriberId(); 1790 mNetworkAgent = new DcNetworkAgent(getHandler().getLooper(), mPhone.getContext(), 1791 "DcNetworkAgent", mNetworkInfo, makeNetworkCapabilities(), mLinkProperties, 1792 50, misc); 1793 } 1794 1795 @Override 1796 public void exit() { 1797 if (DBG) log("DcActiveState: exit dc=" + this); 1798 String reason = mNetworkInfo.getReason(); 1799 if(mDcController.isExecutingCarrierChange()) { 1800 reason = Phone.REASON_CARRIER_CHANGE; 1801 } else if (mDisconnectParams != null && mDisconnectParams.mReason != null) { 1802 reason = mDisconnectParams.mReason; 1803 } else if (mDcFailCause != null) { 1804 reason = mDcFailCause.toString(); 1805 } 1806 mPhone.getCallTracker().unregisterForVoiceCallStarted(getHandler()); 1807 mPhone.getCallTracker().unregisterForVoiceCallEnded(getHandler()); 1808 1809 mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, 1810 reason, mNetworkInfo.getExtraInfo()); 1811 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 1812 mNetworkAgent = null; 1813 } 1814 1815 @Override 1816 public boolean processMessage(Message msg) { 1817 boolean retVal; 1818 1819 switch (msg.what) { 1820 case EVENT_CONNECT: { 1821 ConnectionParams cp = (ConnectionParams) msg.obj; 1822 if (DBG) { 1823 log("DcActiveState: EVENT_CONNECT cp=" + cp + " dc=" + DataConnection.this); 1824 } 1825 if (mApnContexts.contains(cp.mApnContext)) { 1826 log("DcActiveState ERROR already added apnContext=" + cp.mApnContext); 1827 } else { 1828 mApnContexts.add(cp.mApnContext); 1829 if (DBG) { 1830 log("DcActiveState msg.what=EVENT_CONNECT RefCount=" 1831 + mApnContexts.size()); 1832 } 1833 } 1834 notifyConnectCompleted(cp, DcFailCause.NONE, false); 1835 retVal = HANDLED; 1836 break; 1837 } 1838 case EVENT_DISCONNECT: { 1839 DisconnectParams dp = (DisconnectParams) msg.obj; 1840 if (DBG) { 1841 log("DcActiveState: EVENT_DISCONNECT dp=" + dp 1842 + " dc=" + DataConnection.this); 1843 } 1844 if (mApnContexts.contains(dp.mApnContext)) { 1845 if (DBG) { 1846 log("DcActiveState msg.what=EVENT_DISCONNECT RefCount=" 1847 + mApnContexts.size()); 1848 } 1849 1850 if (mApnContexts.size() == 1) { 1851 mApnContexts.clear(); 1852 mDisconnectParams = dp; 1853 mConnectionParams = null; 1854 dp.mTag = mTag; 1855 tearDownData(dp); 1856 transitionTo(mDisconnectingState); 1857 } else { 1858 mApnContexts.remove(dp.mApnContext); 1859 notifyDisconnectCompleted(dp, false); 1860 } 1861 } else { 1862 log("DcActiveState ERROR no such apnContext=" + dp.mApnContext 1863 + " in this dc=" + DataConnection.this); 1864 notifyDisconnectCompleted(dp, false); 1865 } 1866 retVal = HANDLED; 1867 break; 1868 } 1869 case EVENT_DISCONNECT_ALL: { 1870 if (DBG) { 1871 log("DcActiveState EVENT_DISCONNECT clearing apn contexts," 1872 + " dc=" + DataConnection.this); 1873 } 1874 DisconnectParams dp = (DisconnectParams) msg.obj; 1875 mDisconnectParams = dp; 1876 mConnectionParams = null; 1877 dp.mTag = mTag; 1878 tearDownData(dp); 1879 transitionTo(mDisconnectingState); 1880 retVal = HANDLED; 1881 break; 1882 } 1883 case EVENT_LOST_CONNECTION: { 1884 if (DBG) { 1885 log("DcActiveState EVENT_LOST_CONNECTION dc=" + DataConnection.this); 1886 } 1887 if (mRetryManager.isRetryNeeded()) { 1888 // We're going to retry 1889 int delayMillis = mRetryManager.getRetryTimer(); 1890 if (DBG) { 1891 log("DcActiveState EVENT_LOST_CONNECTION startRetryAlarm" 1892 + " mTag=" + mTag + " delay=" + delayMillis + "ms"); 1893 } 1894 mDcRetryAlarmController.startRetryAlarm(EVENT_RETRY_CONNECTION, mTag, 1895 delayMillis); 1896 transitionTo(mRetryingState); 1897 } else { 1898 mInactiveState.setEnterNotificationParams(DcFailCause.LOST_CONNECTION); 1899 transitionTo(mInactiveState); 1900 } 1901 retVal = HANDLED; 1902 break; 1903 } 1904 case EVENT_DATA_CONNECTION_ROAM_ON: { 1905 mNetworkInfo.setRoaming(true); 1906 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 1907 retVal = HANDLED; 1908 break; 1909 } 1910 case EVENT_DATA_CONNECTION_ROAM_OFF: { 1911 mNetworkInfo.setRoaming(false); 1912 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 1913 retVal = HANDLED; 1914 break; 1915 } 1916 case EVENT_BW_REFRESH_RESPONSE: { 1917 AsyncResult ar = (AsyncResult)msg.obj; 1918 if (ar.exception != null) { 1919 log("EVENT_BW_REFRESH_RESPONSE: error ignoring, e=" + ar.exception); 1920 } else { 1921 final ArrayList<Integer> capInfo = (ArrayList<Integer>)ar.result; 1922 final int lceBwDownKbps = capInfo.get(0); 1923 NetworkCapabilities nc = makeNetworkCapabilities(); 1924 if (mPhone.getLceStatus() == RILConstants.LCE_ACTIVE) { 1925 nc.setLinkDownstreamBandwidthKbps(lceBwDownKbps); 1926 if (mNetworkAgent != null) { 1927 mNetworkAgent.sendNetworkCapabilities(nc); 1928 } 1929 } 1930 } 1931 retVal = HANDLED; 1932 break; 1933 } 1934 case EVENT_DATA_CONNECTION_VOICE_CALL_STARTED: 1935 case EVENT_DATA_CONNECTION_VOICE_CALL_ENDED: { 1936 if (updateNetworkInfoSuspendState()) { 1937 // state changed 1938 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 1939 } 1940 retVal = HANDLED; 1941 break; 1942 } 1943 default: 1944 if (VDBG) { 1945 log("DcActiveState not handled msg.what=" + getWhatToString(msg.what)); 1946 } 1947 retVal = NOT_HANDLED; 1948 break; 1949 } 1950 return retVal; 1951 } 1952 } 1953 private DcActiveState mActiveState = new DcActiveState(); 1954 1955 /** 1956 * The state machine is disconnecting. 1957 */ 1958 private class DcDisconnectingState extends State { 1959 @Override 1960 public boolean processMessage(Message msg) { 1961 boolean retVal; 1962 1963 switch (msg.what) { 1964 case EVENT_CONNECT: 1965 if (DBG) log("DcDisconnectingState msg.what=EVENT_CONNECT. Defer. RefCount = " 1966 + mApnContexts.size()); 1967 deferMessage(msg); 1968 retVal = HANDLED; 1969 break; 1970 1971 case EVENT_DEACTIVATE_DONE: 1972 AsyncResult ar = (AsyncResult) msg.obj; 1973 DisconnectParams dp = (DisconnectParams) ar.userObj; 1974 1975 String str = "DcDisconnectingState msg.what=EVENT_DEACTIVATE_DONE RefCount=" 1976 + mApnContexts.size(); 1977 if (DBG) log(str); 1978 if (dp.mApnContext != null) dp.mApnContext.requestLog(str); 1979 1980 if (dp.mTag == mTag) { 1981 // Transition to inactive but send notifications after 1982 // we've entered the mInactive state. 1983 mInactiveState.setEnterNotificationParams((DisconnectParams) ar.userObj); 1984 transitionTo(mInactiveState); 1985 } else { 1986 if (DBG) log("DcDisconnectState stale EVENT_DEACTIVATE_DONE" 1987 + " dp.tag=" + dp.mTag + " mTag=" + mTag); 1988 } 1989 retVal = HANDLED; 1990 break; 1991 1992 default: 1993 if (VDBG) { 1994 log("DcDisconnectingState not handled msg.what=" 1995 + getWhatToString(msg.what)); 1996 } 1997 retVal = NOT_HANDLED; 1998 break; 1999 } 2000 return retVal; 2001 } 2002 } 2003 private DcDisconnectingState mDisconnectingState = new DcDisconnectingState(); 2004 2005 /** 2006 * The state machine is disconnecting after an creating a connection. 2007 */ 2008 private class DcDisconnectionErrorCreatingConnection extends State { 2009 @Override 2010 public boolean processMessage(Message msg) { 2011 boolean retVal; 2012 2013 switch (msg.what) { 2014 case EVENT_DEACTIVATE_DONE: 2015 AsyncResult ar = (AsyncResult) msg.obj; 2016 ConnectionParams cp = (ConnectionParams) ar.userObj; 2017 if (cp.mTag == mTag) { 2018 String str = "DcDisconnectionErrorCreatingConnection" + 2019 " msg.what=EVENT_DEACTIVATE_DONE"; 2020 if (DBG) log(str); 2021 if (cp.mApnContext != null) cp.mApnContext.requestLog(str); 2022 2023 // Transition to inactive but send notifications after 2024 // we've entered the mInactive state. 2025 mInactiveState.setEnterNotificationParams(cp, 2026 DcFailCause.UNACCEPTABLE_NETWORK_PARAMETER); 2027 transitionTo(mInactiveState); 2028 } else { 2029 if (DBG) { 2030 log("DcDisconnectionErrorCreatingConnection stale EVENT_DEACTIVATE_DONE" 2031 + " dp.tag=" + cp.mTag + ", mTag=" + mTag); 2032 } 2033 } 2034 retVal = HANDLED; 2035 break; 2036 2037 default: 2038 if (VDBG) { 2039 log("DcDisconnectionErrorCreatingConnection not handled msg.what=" 2040 + getWhatToString(msg.what)); 2041 } 2042 retVal = NOT_HANDLED; 2043 break; 2044 } 2045 return retVal; 2046 } 2047 } 2048 private DcDisconnectionErrorCreatingConnection mDisconnectingErrorCreatingConnection = 2049 new DcDisconnectionErrorCreatingConnection(); 2050 2051 2052 private class DcNetworkAgent extends NetworkAgent { 2053 public DcNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, 2054 NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) { 2055 super(l, c, TAG, ni, nc, lp, score, misc); 2056 } 2057 2058 @Override 2059 protected void unwanted() { 2060 if (mNetworkAgent != this) { 2061 log("DcNetworkAgent: unwanted found mNetworkAgent=" + mNetworkAgent + 2062 ", which isn't me. Aborting unwanted"); 2063 return; 2064 } 2065 // this can only happen if our exit has been called - we're already disconnected 2066 if (mApnContexts == null) return; 2067 for (ApnContext apnContext : mApnContexts) { 2068 log("DcNetworkAgent: [unwanted]: disconnect apnContext=" + apnContext); 2069 Message msg = mDct.obtainMessage(DctConstants.EVENT_DISCONNECT_DONE, apnContext); 2070 DisconnectParams dp = new DisconnectParams(apnContext, apnContext.getReason(), msg); 2071 DataConnection.this.sendMessage(DataConnection.this. 2072 obtainMessage(EVENT_DISCONNECT, dp)); 2073 } 2074 } 2075 2076 @Override 2077 protected void pollLceData() { 2078 if(mPhone.getLceStatus() == RILConstants.LCE_ACTIVE) { // active LCE service 2079 mPhone.mCi.pullLceData(DataConnection.this.obtainMessage(EVENT_BW_REFRESH_RESPONSE)); 2080 } 2081 } 2082 } 2083 2084 // ******* "public" interface 2085 2086 /** 2087 * Used for testing purposes. 2088 */ 2089 /* package */ void tearDownNow() { 2090 if (DBG) log("tearDownNow()"); 2091 sendMessage(obtainMessage(EVENT_TEAR_DOWN_NOW)); 2092 } 2093 2094 /** 2095 * @return the string for msg.what as our info. 2096 */ 2097 @Override 2098 protected String getWhatToString(int what) { 2099 return cmdToString(what); 2100 } 2101 2102 private static String msgToString(Message msg) { 2103 String retVal; 2104 if (msg == null) { 2105 retVal = "null"; 2106 } else { 2107 StringBuilder b = new StringBuilder(); 2108 2109 b.append("{what="); 2110 b.append(cmdToString(msg.what)); 2111 2112 b.append(" when="); 2113 TimeUtils.formatDuration(msg.getWhen() - SystemClock.uptimeMillis(), b); 2114 2115 if (msg.arg1 != 0) { 2116 b.append(" arg1="); 2117 b.append(msg.arg1); 2118 } 2119 2120 if (msg.arg2 != 0) { 2121 b.append(" arg2="); 2122 b.append(msg.arg2); 2123 } 2124 2125 if (msg.obj != null) { 2126 b.append(" obj="); 2127 b.append(msg.obj); 2128 } 2129 2130 b.append(" target="); 2131 b.append(msg.getTarget()); 2132 2133 b.append(" replyTo="); 2134 b.append(msg.replyTo); 2135 2136 b.append("}"); 2137 2138 retVal = b.toString(); 2139 } 2140 return retVal; 2141 } 2142 2143 static void slog(String s) { 2144 Rlog.d("DC", s); 2145 } 2146 2147 /** 2148 * Log with debug 2149 * 2150 * @param s is string log 2151 */ 2152 @Override 2153 protected void log(String s) { 2154 Rlog.d(getName(), s); 2155 } 2156 2157 /** 2158 * Log with debug attribute 2159 * 2160 * @param s is string log 2161 */ 2162 @Override 2163 protected void logd(String s) { 2164 Rlog.d(getName(), s); 2165 } 2166 2167 /** 2168 * Log with verbose attribute 2169 * 2170 * @param s is string log 2171 */ 2172 @Override 2173 protected void logv(String s) { 2174 Rlog.v(getName(), s); 2175 } 2176 2177 /** 2178 * Log with info attribute 2179 * 2180 * @param s is string log 2181 */ 2182 @Override 2183 protected void logi(String s) { 2184 Rlog.i(getName(), s); 2185 } 2186 2187 /** 2188 * Log with warning attribute 2189 * 2190 * @param s is string log 2191 */ 2192 @Override 2193 protected void logw(String s) { 2194 Rlog.w(getName(), s); 2195 } 2196 2197 /** 2198 * Log with error attribute 2199 * 2200 * @param s is string log 2201 */ 2202 @Override 2203 protected void loge(String s) { 2204 Rlog.e(getName(), s); 2205 } 2206 2207 /** 2208 * Log with error attribute 2209 * 2210 * @param s is string log 2211 * @param e is a Throwable which logs additional information. 2212 */ 2213 @Override 2214 protected void loge(String s, Throwable e) { 2215 Rlog.e(getName(), s, e); 2216 } 2217 2218 /** Doesn't print mApnList of ApnContext's which would be recursive */ 2219 public String toStringSimple() { 2220 return getName() + ": State=" + getCurrentState().getName() 2221 + " mApnSetting=" + mApnSetting + " RefCount=" + mApnContexts.size() 2222 + " mCid=" + mCid + " mCreateTime=" + mCreateTime 2223 + " mLastastFailTime=" + mLastFailTime 2224 + " mLastFailCause=" + mLastFailCause 2225 + " mTag=" + mTag 2226 + " mRetryManager=" + mRetryManager 2227 + " mLinkProperties=" + mLinkProperties 2228 + " linkCapabilities=" + makeNetworkCapabilities(); 2229 } 2230 2231 @Override 2232 public String toString() { 2233 return "{" + toStringSimple() + " mApnContexts=" + mApnContexts + "}"; 2234 } 2235 2236 private void dumpToLog() { 2237 dump(null, new PrintWriter(new StringWriter(0)) { 2238 @Override 2239 public void println(String s) { 2240 DataConnection.this.logd(s); 2241 } 2242 2243 @Override 2244 public void flush() { 2245 } 2246 }, null); 2247 } 2248 2249 /** 2250 * Dump the current state. 2251 * 2252 * @param fd 2253 * @param pw 2254 * @param args 2255 */ 2256 @Override 2257 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2258 pw.print("DataConnection "); 2259 super.dump(fd, pw, args); 2260 pw.println(" mApnContexts.size=" + mApnContexts.size()); 2261 pw.println(" mApnContexts=" + mApnContexts); 2262 pw.flush(); 2263 pw.println(" mDataConnectionTracker=" + mDct); 2264 pw.println(" mApnSetting=" + mApnSetting); 2265 pw.println(" mTag=" + mTag); 2266 pw.println(" mCid=" + mCid); 2267 pw.println(" mRetryManager=" + mRetryManager); 2268 pw.println(" mConnectionParams=" + mConnectionParams); 2269 pw.println(" mDisconnectParams=" + mDisconnectParams); 2270 pw.println(" mDcFailCause=" + mDcFailCause); 2271 pw.flush(); 2272 pw.println(" mPhone=" + mPhone); 2273 pw.flush(); 2274 pw.println(" mLinkProperties=" + mLinkProperties); 2275 pw.flush(); 2276 pw.println(" mDataRegState=" + mDataRegState); 2277 pw.println(" mRilRat=" + mRilRat); 2278 pw.println(" mNetworkCapabilities=" + makeNetworkCapabilities()); 2279 pw.println(" mCreateTime=" + TimeUtils.logTimeOfDay(mCreateTime)); 2280 pw.println(" mLastFailTime=" + TimeUtils.logTimeOfDay(mLastFailTime)); 2281 pw.println(" mLastFailCause=" + mLastFailCause); 2282 pw.flush(); 2283 pw.println(" mUserData=" + mUserData); 2284 pw.println(" mInstanceNumber=" + mInstanceNumber); 2285 pw.println(" mAc=" + mAc); 2286 pw.println(" mDcRetryAlarmController=" + mDcRetryAlarmController); 2287 pw.flush(); 2288 } 2289} 2290