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