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