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